Skip to main content

volga_oauth_client/
config.rs

1//! Client configuration
2//!
3//! [`ClientConfig`] carries the transport-level policy shared by all client
4//! operations (discovery, token requests, registration): HTTPS enforcement,
5//! timeouts and redirect limits. The defaults are safe for production use.
6
7use std::time::Duration;
8
9/// Default total timeout for a single client request
10pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(30);
11
12/// Default maximum number of redirects followed per request
13pub const DEFAULT_MAX_REDIRECTS: u8 = 5;
14
15/// Transport-level configuration for OAuth client operations
16///
17/// # Example
18/// ```
19/// use std::time::Duration;
20/// use volga_oauth_client::ClientConfig;
21///
22/// let config = ClientConfig::new()
23///     .with_timeout(Duration::from_secs(5))
24///     .with_max_redirects(0);
25///
26/// assert!(config.enforce_https());
27/// ```
28#[derive(Clone, Debug, PartialEq, Eq)]
29pub struct ClientConfig {
30    enforce_https: bool,
31    timeout: Duration,
32    max_redirects: u8,
33}
34
35impl Default for ClientConfig {
36    #[inline]
37    fn default() -> Self {
38        Self {
39            enforce_https: true,
40            timeout: DEFAULT_TIMEOUT,
41            max_redirects: DEFAULT_MAX_REDIRECTS,
42        }
43    }
44}
45
46impl ClientConfig {
47    /// Creates a configuration with the default policy: HTTPS enforced,
48    /// [`DEFAULT_TIMEOUT`] and [`DEFAULT_MAX_REDIRECTS`]
49    #[inline]
50    pub fn new() -> Self {
51        Self::default()
52    }
53
54    /// Controls whether plain `http://` URLs are rejected
55    ///
56    /// Enabled by default. Disable only for local development against a
57    /// plaintext authorization server; requests to `http://` endpoints
58    /// otherwise fail with
59    /// [`ClientError::InsecureUrl`](crate::ClientError::InsecureUrl).
60    #[inline]
61    pub fn require_https(mut self, required: bool) -> Self {
62        self.enforce_https = required;
63        self
64    }
65
66    /// Sets the total timeout for a single request
67    #[inline]
68    pub fn with_timeout(mut self, timeout: Duration) -> Self {
69        self.timeout = timeout;
70        self
71    }
72
73    /// Sets the maximum number of redirects followed per request;
74    /// `0` disables redirects entirely
75    #[inline]
76    pub fn with_max_redirects(mut self, max_redirects: u8) -> Self {
77        self.max_redirects = max_redirects;
78        self
79    }
80
81    /// Returns whether plain `http://` URLs are rejected
82    #[inline]
83    pub fn enforce_https(&self) -> bool {
84        self.enforce_https
85    }
86
87    /// Returns the total timeout for a single request
88    #[inline]
89    pub fn timeout(&self) -> Duration {
90        self.timeout
91    }
92
93    /// Returns the maximum number of redirects followed per request
94    #[inline]
95    pub fn max_redirects(&self) -> u8 {
96        self.max_redirects
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103
104    #[test]
105    fn it_defaults_to_safe_policy() {
106        let config = ClientConfig::new();
107        assert!(config.enforce_https());
108        assert_eq!(config.timeout(), DEFAULT_TIMEOUT);
109        assert_eq!(config.max_redirects(), DEFAULT_MAX_REDIRECTS);
110    }
111
112    #[test]
113    fn it_builds_custom_policy() {
114        let config = ClientConfig::new()
115            .require_https(false)
116            .with_timeout(Duration::from_secs(5))
117            .with_max_redirects(0);
118        assert!(!config.enforce_https());
119        assert_eq!(config.timeout(), Duration::from_secs(5));
120        assert_eq!(config.max_redirects(), 0);
121    }
122}