Skip to main content

cloud_sdk_reqwest/shared/
config.rs

1use core::fmt;
2use std::time::Duration;
3
4use reqwest::header::HeaderValue;
5
6/// Maximum configured timeout accepted by the adapter.
7pub const MAX_TIMEOUT_SECONDS: u64 = 300;
8
9/// Timeout policy validation error.
10#[derive(Clone, Copy, Debug, Eq, PartialEq)]
11pub enum TimeoutError {
12    /// Every timeout must be nonzero.
13    Zero,
14    /// Every timeout is capped at [`MAX_TIMEOUT_SECONDS`].
15    TooLong,
16    /// The connect timeout must not exceed the total timeout.
17    ExceedsTotal,
18}
19
20/// Explicit total-request and connection timeout policy.
21#[derive(Clone, Copy, Debug, Eq, PartialEq)]
22pub struct RequestTimeouts {
23    total: Duration,
24    connect: Duration,
25}
26
27impl RequestTimeouts {
28    /// Validates all timeout dimensions.
29    pub fn new(total: Duration, connect: Duration) -> Result<Self, TimeoutError> {
30        if total.is_zero() || connect.is_zero() {
31            return Err(TimeoutError::Zero);
32        }
33        let maximum = Duration::from_secs(MAX_TIMEOUT_SECONDS);
34        if total > maximum || connect > maximum {
35            return Err(TimeoutError::TooLong);
36        }
37        if connect > total {
38            return Err(TimeoutError::ExceedsTotal);
39        }
40        Ok(Self { total, connect })
41    }
42
43    pub(crate) const fn total(self) -> Duration {
44        self.total
45    }
46
47    pub(crate) const fn connect(self) -> Duration {
48        self.connect
49    }
50}
51
52/// User-agent validation error.
53#[derive(Clone, Copy, Debug, Eq, PartialEq)]
54pub enum UserAgentError {
55    /// User agents must not be empty.
56    Empty,
57    /// User agents are capped at 256 bytes.
58    TooLong,
59    /// The value is not a valid HTTP header value.
60    Invalid,
61}
62
63/// Validated, non-secret user-agent header value.
64#[derive(Clone)]
65pub struct UserAgent {
66    pub(crate) value: HeaderValue,
67}
68
69impl UserAgent {
70    /// Validates a user-agent value.
71    pub fn new(value: &str) -> Result<Self, UserAgentError> {
72        if value.is_empty() {
73            return Err(UserAgentError::Empty);
74        }
75        if value.len() > 256 {
76            return Err(UserAgentError::TooLong);
77        }
78        let value = HeaderValue::from_str(value).map_err(|_| UserAgentError::Invalid)?;
79        Ok(Self { value })
80    }
81}
82
83impl fmt::Debug for UserAgent {
84    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
85        formatter.write_str("UserAgent([validated])")
86    }
87}