squareup/http/client/
http_client_configuration.rs

1//! Configuration for HTTP client settings
2
3use package_info::PackageInfo;
4use std::default::Default;
5use std::env;
6use std::time::Duration;
7
8use crate::{config::CargoPackageInfo, http::Headers};
9
10const DEFAULT_TIMEOUT: u32 = 60;
11
12/// Configuration for HTTP client settings
13#[derive(Clone, Debug)]
14pub struct HttpClientConfiguration {
15    /// Timeout for HTTP connections
16    pub timeout: u32,
17    /// User Agent to use for requests
18    pub user_agent: String,
19    /// Headers to send with each request
20    pub default_headers: Headers,
21    /// Retry mechanism configuration
22    pub retry_configuration: RetryConfiguration,
23}
24
25#[derive(Clone, Debug, Eq, PartialEq)]
26pub struct RetryConfiguration {
27    /// How many times client should call same request in case of failure.
28    /// Square now makes a maximum of 11 retry attempts for up to 24 hours after the event.
29    /// This change applies to webhook subscriptions for all Square API versions.
30    pub retries_count: u32,
31    /// Minimum waiting time between two retry attempts (it can end up being lower due to jittering).
32    pub min_retry_interval: Duration,
33    /// Maximum waiting time between two retry attempts.
34    pub max_retry_interval: Duration,
35    /// Growing factor governing how fast the retry interval increases with respect to the number
36    /// of failed attempts. If set to 3:
37    /// - first retry: 3^0 = 1
38    /// - second retry: 3^1 = 3
39    /// - third retry: 3^2 = 9
40    pub base: u32,
41}
42
43impl Default for RetryConfiguration {
44    fn default() -> Self {
45        Self {
46            retries_count: 0,
47            min_retry_interval: Duration::from_secs(1),
48            max_retry_interval: Duration::from_secs(30 * 60),
49            base: 3,
50        }
51    }
52}
53
54impl HttpClientConfiguration {
55    /// Instantiates a new `HttpClientConfiguration` based on the specified settings.
56    /// If the User Agent is not included in the default headers, it'll be added.
57    pub fn new(timeout: u32, user_agent: String, mut default_headers: Headers) -> Self {
58        if !default_headers.has_user_agent() {
59            default_headers.set_user_agent(&user_agent);
60        }
61        Self {
62            timeout,
63            user_agent,
64            default_headers,
65            retry_configuration: Default::default(),
66        }
67    }
68
69    /// Provides the library/crate's default User Agent
70    pub(crate) fn default_user_agent() -> String {
71        let sdk_version = CargoPackageInfo::version().unwrap_or_default();
72        let engine = "Rust";
73        let rust_version = rustc_version_runtime::version();
74        let os = env::consts::OS;
75        format!(
76            "Rust Square API Client Lib ({}) {}/{} ({})",
77            sdk_version, engine, rust_version, os
78        )
79    }
80}
81
82impl Default for HttpClientConfiguration {
83    /// The default HTTP client settings
84    fn default() -> Self {
85        Self {
86            timeout: DEFAULT_TIMEOUT,
87            user_agent: Self::default_user_agent(),
88            default_headers: Default::default(),
89            retry_configuration: Default::default(),
90        }
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use crate::http::Headers;
97    use crate::http::client::{HttpClientConfiguration, RetryConfiguration};
98
99    #[test]
100    fn http_client_configuration_new_with_default_headers() {
101        let http_client_configuration =
102            HttpClientConfiguration::new(15, String::from("some_user_agent"), Headers::default());
103        assert_eq!(15, http_client_configuration.timeout);
104        assert_eq!(
105            String::from("some_user_agent"),
106            http_client_configuration.user_agent
107        );
108        assert_eq!(
109            Headers::default(),
110            http_client_configuration.default_headers
111        );
112        assert_eq!(
113            RetryConfiguration::default(),
114            http_client_configuration.retry_configuration
115        );
116    }
117
118    #[test]
119    fn http_client_configuration_new_with_different_user_agent_in_headers() {
120        // Headers::
121        let http_client_configuration =
122            HttpClientConfiguration::new(15, String::from("some_user_agent"), Headers::default());
123        assert_eq!(15, http_client_configuration.timeout);
124        assert_eq!(
125            String::from("some_user_agent"),
126            http_client_configuration.user_agent
127        );
128        assert_eq!(
129            Headers::default(),
130            http_client_configuration.default_headers
131        );
132        assert_eq!(
133            RetryConfiguration::default(),
134            http_client_configuration.retry_configuration
135        );
136    }
137}