nbp 0.2.0

A Rust library for accessing the National Bank of Poland's API.
Documentation
use crate::nbp_error::{NbpError, NbpResult};
use reqwest::{Client, StatusCode};
use url::Url;

#[derive(Clone, Debug)]
pub struct ServiceClient {
    http_client: Client,
    base_url: Url,
}

impl ServiceClient {
    pub fn new(base_url: Url) -> Self {
        let mut headers = reqwest::header::HeaderMap::new();
        headers.append(
            reqwest::header::ACCEPT,
            reqwest::header::HeaderValue::from_static("application/json"),
        );
        let http_client = Client::builder().default_headers(headers).build().unwrap();

        Self {
            http_client,
            base_url,
        }
    }

    pub fn join_path(&mut self, path: &str) -> NbpResult<()> {
        self.base_url = self.base_url.join(path).map_err(|e| {
            NbpError::InvalidArgument(format!("Failed to join path '{}': {}", path, e))
        })?;
        Ok(())
    }

    pub async fn get<T>(&self) -> NbpResult<T>
    where
        T: serde::de::DeserializeOwned,
    {
        let response = self
            .http_client
            .get(self.base_url.clone())
            .send()
            .await
            .map_err(|e| NbpError::RequestFailed(e.to_string()))?;

        match response.status() {
            StatusCode::NOT_FOUND => {
                return Err(NbpError::NotFound(format!(
                    "Resource not found for route {}",
                    self.base_url
                )));
            }
            StatusCode::BAD_REQUEST => {
                return Err(NbpError::BadRequest(format!(
                    "Bad request for route {}",
                    self.base_url
                )));
            }
            StatusCode::INTERNAL_SERVER_ERROR => {
                return Err(NbpError::InternalError(format!(
                    "Internal server error for route {}",
                    self.base_url
                )));
            }
            status if status.is_success() => {}
            status => {
                return Err(NbpError::HttpError(status.as_u16()));
            }
        }

        response.json::<T>().await.map_err(|e| {
            NbpError::CannotDeserializeBody(format!(
                "Failed to deserialize response for route {}: {}",
                self.base_url, e
            ))
        })
    }
}