Skip to main content

cyberdrop_client/
lib.rs

1//! Cyberdrop API client.
2//!
3//! This crate provides a small, async wrapper around a subset of Cyberdrop's HTTP API.
4//! It is built on [`reqwest`] and is intended to be copy-paste friendly in CLI tools and
5//! simple services.
6//!
7//! ## Quickstart
8//!
9//! Authenticate, then call endpoints that require a token:
10//!
11//! ```no_run
12//! use cyberdrop_client::CyberdropClient;
13//! use std::path::Path;
14//!
15//! # #[tokio::main]
16//! # async fn main() -> Result<(), cyberdrop_client::CyberdropError> {
17//! // 1) Create an unauthenticated client.
18//! let client = CyberdropClient::builder().build()?;
19//!
20//! // 2) Exchange credentials for a token.
21//! let token = client.login("username", "password").await?;
22//!
23//! // 3) Use a cloned client that includes the token on authenticated requests.
24//! let authed = client.with_auth_token(token.into_string());
25//! let albums = authed.list_albums().await?;
26//! println!("albums: {}", albums.albums.len());
27//!
28//! // 4) Create an album and upload a file into it.
29//! let album_id = authed
30//!     .create_album("my uploads", Some("created by cyberdrop-client"))
31//!     .await?;
32//! let uploaded = authed
33//!     .upload_file(Path::new("path/to/file.jpg"), Some(album_id))
34//!     .await?;
35//! println!("uploaded {} -> {}", uploaded.name, uploaded.url);
36//! # Ok(())
37//! # }
38//! ```
39//!
40//! Note: `upload_file` streams smaller files and reads larger files in chunks.
41//!
42//! ## Authentication
43//!
44//! Authenticated endpoints use an HTTP header named `token` (not an `Authorization: Bearer ...`
45//! header). Methods that *require* authentication return [`CyberdropError::MissingAuthToken`]
46//! if no token is configured.
47//!
48//! ## Timeouts, Retries, Polling
49//!
50//! - **Timeouts:** The client uses a single *request* timeout configured via
51//!   [`CyberdropClientBuilder::timeout`]. The default is 30 seconds. Timeout failures surface as
52//!   [`CyberdropError::Http`] (from `reqwest`).
53//! - **Retries:** This crate does not implement retries, backoff, or idempotency safeguards.
54//!   If you need retries, add them at the call site.
55//! - **Polling:** This crate does not poll for eventual consistency. Methods return once the HTTP
56//!   request/response completes.
57//!
58//! ## Error Model
59//!
60//! Higher-level API methods (for example, [`CyberdropClient::list_albums`]) treat non-2xx HTTP
61//! responses as errors:
62//! - `401`/`403` become [`CyberdropError::AuthenticationFailed`]
63//! - other non-2xx statuses become [`CyberdropError::RequestFailed`]
64//!
65//! In contrast, [`CyberdropClient::get`] is low-level and returns the raw response even for
66//! non-2xx statuses.
67//!
68//! External system failures are surfaced as:
69//! - [`CyberdropError::Io`] when reading local files (for example, in [`CyberdropClient::upload_file`])
70//! - [`CyberdropError::Http`] for network/transport failures (DNS, TLS, connection errors, timeouts)
71//!
72//! ## Base URL Semantics
73//!
74//! The base URL is joined with relative paths via [`Url::join`]. If you supply a custom base URL,
75//! prefer including a trailing slash (for example, `https://example.test/`), so relative joins
76//! behave as expected.
77//!
78//! ## Low-Level Requests
79//!
80//! [`CyberdropClient::get`] is intentionally low-level: it returns the raw [`reqwest::Response`]
81//! and does **not** treat non-2xx status codes as errors.
82
83mod client;
84mod error;
85mod models;
86mod transport;
87
88pub(crate) use client::ChunkFields;
89pub use client::{CyberdropClient, CyberdropClientBuilder};
90pub use error::CyberdropError;
91pub use models::{
92    Album, AlbumFile, AlbumFilesPage, AlbumsList, AuthToken, EditAlbumResult, Permissions,
93    TokenVerification, UploadProgress, UploadedFile,
94};