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: the current `upload_file` implementation reads the entire file into memory before
41//! uploading.
42//!
43//! ## Authentication
44//!
45//! Authenticated endpoints use an HTTP header named `token` (not an `Authorization: Bearer ...`
46//! header). Methods that *require* authentication return [`CyberdropError::MissingAuthToken`]
47//! if no token is configured.
48//!
49//! ## Timeouts, Retries, Polling
50//!
51//! - **Timeouts:** The client uses a single *request* timeout configured via
52//!   [`CyberdropClientBuilder::timeout`]. The default is 30 seconds. Timeout failures surface as
53//!   [`CyberdropError::Http`] (from `reqwest`).
54//! - **Retries:** This crate does not implement retries, backoff, or idempotency safeguards.
55//!   If you need retries, add them at the call site.
56//! - **Polling:** This crate does not poll for eventual consistency. Methods return once the HTTP
57//!   request/response completes.
58//!
59//! ## Error Model
60//!
61//! Higher-level API methods (for example, [`CyberdropClient::list_albums`]) treat non-2xx HTTP
62//! responses as errors:
63//! - `401`/`403` become [`CyberdropError::AuthenticationFailed`]
64//! - other non-2xx statuses become [`CyberdropError::RequestFailed`]
65//!
66//! In contrast, [`CyberdropClient::get`] is low-level and returns the raw response even for
67//! non-2xx statuses.
68//!
69//! External system failures are surfaced as:
70//! - [`CyberdropError::Io`] when reading local files (for example, in [`CyberdropClient::upload_file`])
71//! - [`CyberdropError::Http`] for network/transport failures (DNS, TLS, connection errors, timeouts)
72//!
73//! ## Base URL Semantics
74//!
75//! The base URL is joined with relative paths via [`Url::join`]. If you supply a custom base URL,
76//! prefer including a trailing slash (for example, `https://example.test/`), so relative joins
77//! behave as expected.
78//!
79//! ## Low-Level Requests
80//!
81//! [`CyberdropClient::get`] is intentionally low-level: it returns the raw [`reqwest::Response`]
82//! and does **not** treat non-2xx status codes as errors.
83
84mod client;
85mod error;
86mod models;
87mod transport;
88
89pub(crate) use client::ChunkFields;
90pub use client::{CyberdropClient, CyberdropClientBuilder};
91pub use error::CyberdropError;
92pub use models::{
93    Album, AlbumFile, AlbumFilesPage, AlbumsList, AuthToken, EditAlbumResult, Permissions,
94    TokenVerification, UploadedFile,
95};