Skip to main content

reqwest_rest/
common_config.rs

1use crate::LoggingRetryableStrategy;
2use reqwest::ClientBuilder;
3use reqwest_middleware::ClientBuilder as ClientWithMiddlewareBuilder;
4use reqwest_retry::{RetryTransientMiddleware, policies::ExponentialBackoff};
5use std::time::Duration;
6
7/// Configuration of timeouts and retries for basic http client, with sane defaults
8#[derive(Clone, Debug)]
9#[non_exhaustive]
10pub struct CommonRestConfig {
11    /// Fail if we can't connect in this amount of time
12    pub connect_timeout: Duration,
13    /// Fail if we don't get a response in this amount of time
14    pub request_timeout: Duration,
15    /// Setting for tcp keepalive interval
16    pub tcp_keepalive: Duration,
17    /// Max retries for transient or 5xx type errors
18    pub max_retries: u32,
19    /// Bounds for the exponential backoff retry policy
20    pub retry_backoff_bounds: (Duration, Duration),
21}
22
23impl Default for CommonRestConfig {
24    fn default() -> Self {
25        Self {
26            connect_timeout: Duration::from_secs(3),
27            request_timeout: Duration::from_secs(3),
28            tcp_keepalive: Duration::from_secs(60),
29            max_retries: 3,
30            retry_backoff_bounds: (Duration::from_millis(50), Duration::from_millis(500)),
31        }
32    }
33}
34
35impl CommonRestConfig {
36    /// Apply settings from CommonRestConfig to a reqwest::ClientBuilder (which may already have other options set).
37    /// Then build a ClientWithMiddleware builder, attach configured RetryTransientMiddleware, and return the builder.
38    /// Further middleware may then be attached, and build may be called.
39    pub fn apply_to_builder(
40        &self,
41        builder: ClientBuilder,
42    ) -> Result<ClientWithMiddlewareBuilder, reqwest::Error> {
43        let client = builder
44            .connect_timeout(self.connect_timeout)
45            .timeout(self.request_timeout)
46            .tcp_keepalive(self.tcp_keepalive)
47            .build()?;
48
49        // Attach middleware
50        let retry_policy = ExponentialBackoff::builder()
51            .retry_bounds(self.retry_backoff_bounds.0, self.retry_backoff_bounds.1)
52            .build_with_max_retries(self.max_retries);
53        let retry_middleware = RetryTransientMiddleware::new_with_policy_and_strategy(
54            retry_policy,
55            LoggingRetryableStrategy::default(),
56        );
57
58        Ok(ClientWithMiddlewareBuilder::new(client).with(retry_middleware))
59    }
60}