Skip to main content

archive_it_client/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use std::fmt::Write;
4use std::time::Duration;
5
6mod error;
7mod http;
8pub mod models;
9pub mod partner;
10pub mod public;
11pub mod wasapi;
12
13pub use error::Error;
14
15/// The transfer engine powering the `download*` methods. Re-exported so callers
16/// can name [`http_ferry::Error`] — the error carried by [`DownloadOutcome`] —
17/// and the [`DownloadLocation`] trait.
18pub use http_ferry;
19pub use http_ferry::DownloadLocation;
20
21/// Per-file outcome of a `WasapiClient::download*` stream. An alias for the
22/// transfer engine's [`Outcome`](http_ferry::Outcome) carrying a
23/// [`WasapiFile`](models::wasapi::WasapiFile); its `error` field is an
24/// [`http_ferry::Error`].
25pub type DownloadOutcome<L = std::path::PathBuf> =
26    http_ferry::Outcome<crate::models::wasapi::WasapiFile, L>;
27
28pub use partner::PartnerClient;
29pub use public::PublicClient;
30pub use wasapi::{WasapiClient, WebdataQuery};
31
32/// User-facing types for the S3 download destination.
33///
34/// Construct an [`aws_sdk_s3::Client`] and pass it to
35/// [`WasapiClient::download_to_s3`] or
36/// [`WasapiClient::download_collection_to_s3`] alongside a bucket and
37/// optional key prefix. Each upload's resolved [`S3Location`](s3::S3Location)
38/// is reported back via `DownloadOutcome`.
39pub mod s3 {
40    pub use http_ferry::s3::S3Location;
41}
42
43pub const USER_AGENT: &str = concat!("Archive-It-Client (", env!("CARGO_PKG_VERSION"), ")");
44
45pub fn sha1_hex(bytes: impl AsRef<[u8]>) -> String {
46    let bytes = bytes.as_ref();
47    let mut hex = String::with_capacity(bytes.len() * 2);
48    for b in bytes {
49        write!(&mut hex, "{b:02x}").expect("writing to String cannot fail");
50    }
51    hex
52}
53
54#[derive(Debug, Default, Clone, Copy, serde::Serialize)]
55pub struct PageOpts {
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub limit: Option<u32>,
58    #[serde(skip_serializing_if = "Option::is_none")]
59    pub offset: Option<u32>,
60}
61
62#[derive(Debug, Clone)]
63pub struct Config {
64    pub base_url: String,
65    pub timeout: Duration,
66    pub download_timeout: Duration,
67    pub max_attempts: u32,
68    pub backoff: Duration,
69    /// Extra headers sent with every request, including WARC downloads,
70    /// e.g. an access token like `("X-Custom-Header", "token-...")`.
71    /// Values are marked sensitive so they are redacted from debug output.
72    /// Invalid names or values are rejected when the client is constructed.
73    pub headers: Vec<(String, String)>,
74}
75
76impl Config {
77    pub fn api() -> Self {
78        Self {
79            base_url: "https://partner.archive-it.org/api/".into(),
80            timeout: Duration::from_secs(30),
81            download_timeout: Duration::from_secs(30),
82            max_attempts: 3,
83            backoff: Duration::from_millis(250),
84            headers: Vec::new(),
85        }
86    }
87
88    pub fn wasapi() -> Self {
89        Self {
90            base_url: "https://partner.archive-it.org/wasapi/v1/".into(),
91            timeout: Duration::from_secs(60),
92            download_timeout: Duration::from_secs(300),
93            ..Self::api()
94        }
95    }
96}