spacetraders-client 0.1.0

Async Rust client for the SpaceTraders API v2 with priority-aware rate limiting and retry
Documentation
mod error;
mod scheduler;
mod send;
mod utils;

pub use error::{ClientError, RetryPolicy};
pub use scheduler::{RequestPriority, RequestScheduler};
pub use utils::{RequestActivitySnapshot, request_activity_snapshot};

pub(crate) type PError<E> = progenitor_client::Error<E>;
pub(crate) use utils::{classify_status, retry_after_from_headers};

pub struct StClient {
    pub(crate) base_url: String,
    pub(crate) token: String,
    pub(crate) scheduler: RequestScheduler,
    pub(crate) http: reqwest::Client,
    pub(crate) inner: crate::generated::Client,
}

impl StClient {
    /// Construct a client against `base_url` (e.g. `https://api.spacetraders.io/v2`)
    /// authenticated with `token`, sharing the given [`RequestScheduler`] for
    /// rate limiting. Clone a single scheduler across clients to share one budget.
    ///
    /// ```no_run
    /// use spacetraders_client::{RequestScheduler, StClient};
    ///
    /// let client = StClient::new(
    ///     "https://api.spacetraders.io/v2",
    ///     std::env::var("AGENT_TOKEN").unwrap(),
    ///     RequestScheduler::new(2), // sustained requests per second
    /// );
    /// ```
    pub fn new(base_url: &str, token: String, scheduler: RequestScheduler) -> Self {
        let base_url = base_url.trim_end_matches('/').to_string();
        let inner = Self::build_inner(&base_url, &token);
        Self {
            base_url,
            token,
            scheduler,
            http: reqwest::Client::new(),
            inner,
        }
    }

    fn build_inner(base_url: &str, token: &str) -> crate::generated::Client {
        let mut headers = reqwest::header::HeaderMap::new();
        headers.insert(
            reqwest::header::AUTHORIZATION,
            format!("Bearer {token}")
                .parse()
                .expect("invalid bearer token"),
        );
        let http = reqwest::Client::builder()
            .default_headers(headers)
            .build()
            .expect("failed to build reqwest client");
        crate::generated::Client::new_with_client(base_url, http)
    }

    pub fn set_token(&mut self, token: String) {
        self.token = token.clone();
        self.inner = Self::build_inner(&self.base_url, &token);
    }

    pub fn token(&self) -> &str {
        &self.token
    }
}