flightradarapi 0.1.0

A modern async Rust SDK for the FlightRadar24 API
Documentation
use std::time::Duration;

use url::Url;

use crate::error::{FlightRadarError, Result};

const DEFAULT_BASE_URL: &str = "https://fr24api.flightradar24.com";
const DEFAULT_USER_AGENT: &str = "flightradarapi-rust/0.1.0";

/// Configuration for the underlying HTTP client.
///
/// This type controls network behavior (timeouts, retries, and base URL)
/// used by [`FlightRadarApi`](crate::FlightRadarApi).
#[derive(Debug, Clone)]
pub struct ClientConfig {
    /// Base URL of the FlightRadar24 API.
    pub base_url: Url,
    /// Per-request timeout.
    pub timeout: Duration,
    /// User-Agent sent with each request.
    pub user_agent: String,
    /// Number of retry attempts on recoverable server errors.
    pub retry_attempts: u8,
}

impl ClientConfig {
    /// Build configuration from a custom API base URL.
    pub fn with_base_url(base_url: impl AsRef<str>) -> Result<Self> {
        Ok(Self {
            base_url: Url::parse(base_url.as_ref())?,
            ..Self::default()
        })
    }

    /// Set request timeout.
    pub fn set_timeout(mut self, timeout: Duration) -> Self {
        self.timeout = timeout;
        self
    }

    /// Set request User-Agent.
    pub fn set_user_agent(mut self, user_agent: impl Into<String>) -> Self {
        self.user_agent = user_agent.into();
        self
    }

    /// Set the number of retry attempts.
    pub fn set_retry_attempts(mut self, attempts: u8) -> Self {
        self.retry_attempts = attempts;
        self
    }

    /// Set API base URL.
    pub fn set_base_url(mut self, base_url: impl AsRef<str>) -> Result<Self> {
        self.base_url = Url::parse(base_url.as_ref())?;
        Ok(self)
    }

    /// Validate configuration values.
    pub fn validate(&self) -> Result<()> {
        if self.user_agent.trim().is_empty() {
            return Err(FlightRadarError::InvalidInput(
                "user agent must not be empty",
            ));
        }

        if self.timeout.is_zero() {
            return Err(FlightRadarError::InvalidInput(
                "timeout must be greater than zero",
            ));
        }

        Ok(())
    }
}

impl Default for ClientConfig {
    fn default() -> Self {
        Self {
            base_url: Url::parse(DEFAULT_BASE_URL)
                .expect("DEFAULT_BASE_URL is a valid URL literal"),
            timeout: Duration::from_secs(10),
            user_agent: DEFAULT_USER_AGENT.to_owned(),
            retry_attempts: 2,
        }
    }
}