bunny_api/
client.rs

1use std::ops::Deref;
2
3use reqwest::{header::{HeaderMap, HeaderValue, InvalidHeaderValue}, Request, Response};
4
5/// Errors that may occur when creating a new [`Client`].
6#[derive(Debug, thiserror::Error)]
7#[allow(clippy::module_name_repetitions)]
8pub enum ClientError {
9    /// The provided access key is not a valid header value.
10    #[error("failed to set access key header: {0}")]
11    AccessKey(#[from] InvalidHeaderValue),
12    /// Failed to build the [`Client`] for some reason.
13    #[error("failed to build client: {0}")]
14    BuildClient(#[from] reqwest::Error),
15}
16
17/// API Client initialized with an API access key.
18#[derive(Debug)]
19pub struct Client(reqwest::Client);
20
21impl Client {
22    /// Create a new `Client` using the given access key.
23    ///
24    /// The client is configured to always use HTTPS.
25    ///
26    /// # Errors
27    ///
28    /// See [`ClientError`].
29    pub fn new(access_key: &str) -> Result<Self, ClientError> {
30        let access_key = HeaderValue::from_str(access_key)?;
31        let mut headers = HeaderMap::with_capacity(1);
32        headers.insert("AccessKey", access_key);
33        let inner = reqwest::Client::builder()
34            .default_headers(headers)
35            .https_only(true)
36            .build()?;
37        Ok(Self(inner))
38    }
39
40    pub(crate) async fn send_logged(&self, req: Request) -> Result<Response, reqwest::Error> {
41        #[cfg(feature = "tracing")]
42        tracing::debug!(
43            method=%req.method(),
44            url=%req.url(),
45            headers=?req.headers(),
46            "about to send request",
47        );
48
49        self.execute(req).await
50    }
51}
52
53impl Deref for Client {
54    type Target = reqwest::Client;
55
56    fn deref(&self) -> &Self::Target {
57        &self.0
58    }
59}