Skip to main content

hpx/client/http/
config_groups.rs

1use std::{num::NonZeroU32, time::Duration};
2
3use crate::{
4    Proxy,
5    client::{
6        conn::TcpConnectOptions,
7        layer::{recovery::Recoveries, timeout::TimeoutOptions},
8    },
9    redirect, retry,
10    tls::{CertStore, Identity, KeyLog, TlsVersion},
11};
12
13/// HTTP protocol preference for grouped client configuration.
14#[derive(Clone, Copy, Default, Eq, PartialEq)]
15pub enum HttpVersionPreference {
16    /// Only negotiate HTTP/1.
17    Http1,
18    /// Only negotiate HTTP/2.
19    Http2,
20    /// Allow the client to negotiate the best supported protocol.
21    #[default]
22    All,
23}
24
25/// Reusable transport-layer settings for a [`crate::ClientBuilder`].
26///
27/// Applying a grouped config replaces the current transport group on the builder.
28#[must_use]
29#[derive(Clone)]
30pub struct TransportConfigOptions {
31    pub(crate) connect_timeout: Option<Duration>,
32    pub(crate) connection_verbose: bool,
33    pub(crate) tcp_nodelay: bool,
34    pub(crate) tcp_reuse_address: bool,
35    pub(crate) tcp_keepalive: Option<Duration>,
36    pub(crate) tcp_keepalive_interval: Option<Duration>,
37    pub(crate) tcp_keepalive_retries: Option<u32>,
38    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
39    pub(crate) tcp_user_timeout: Option<Duration>,
40    pub(crate) tcp_send_buffer_size: Option<usize>,
41    pub(crate) tcp_recv_buffer_size: Option<usize>,
42    pub(crate) tcp_happy_eyeballs_timeout: Option<Duration>,
43    pub(crate) tcp_connect_options: TcpConnectOptions,
44}
45
46impl Default for TransportConfigOptions {
47    fn default() -> Self {
48        Self {
49            connect_timeout: None,
50            connection_verbose: false,
51            tcp_nodelay: true,
52            tcp_reuse_address: false,
53            tcp_keepalive: Some(Duration::from_secs(15)),
54            tcp_keepalive_interval: Some(Duration::from_secs(15)),
55            tcp_keepalive_retries: Some(3),
56            #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
57            tcp_user_timeout: Some(Duration::from_secs(30)),
58            tcp_send_buffer_size: None,
59            tcp_recv_buffer_size: None,
60            tcp_happy_eyeballs_timeout: Some(Duration::from_millis(300)),
61            tcp_connect_options: TcpConnectOptions::default(),
62        }
63    }
64}
65
66impl TransportConfigOptions {
67    /// Create a transport config with the client defaults.
68    pub fn new() -> Self {
69        Self::default()
70    }
71
72    /// Set the connector timeout used for TCP and TLS establishment.
73    pub fn connect_timeout<D>(mut self, timeout: D) -> Self
74    where
75        D: Into<Option<Duration>>,
76    {
77        self.connect_timeout = timeout.into();
78        self
79    }
80
81    /// Enable or disable verbose transport logging.
82    pub fn connection_verbose(mut self, verbose: bool) -> Self {
83        self.connection_verbose = verbose;
84        self
85    }
86
87    /// Set whether sockets use `TCP_NODELAY`.
88    pub fn tcp_nodelay(mut self, enabled: bool) -> Self {
89        self.tcp_nodelay = enabled;
90        self
91    }
92
93    /// Set whether sockets use `SO_REUSEADDR`.
94    pub fn tcp_reuse_address(mut self, enabled: bool) -> Self {
95        self.tcp_reuse_address = enabled;
96        self
97    }
98
99    /// Set the keepalive duration.
100    pub fn tcp_keepalive<D>(mut self, value: D) -> Self
101    where
102        D: Into<Option<Duration>>,
103    {
104        self.tcp_keepalive = value.into();
105        self
106    }
107
108    /// Set the keepalive interval.
109    pub fn tcp_keepalive_interval<D>(mut self, value: D) -> Self
110    where
111        D: Into<Option<Duration>>,
112    {
113        self.tcp_keepalive_interval = value.into();
114        self
115    }
116
117    /// Set the keepalive retry count.
118    pub fn tcp_keepalive_retries<C>(mut self, retries: C) -> Self
119    where
120        C: Into<Option<u32>>,
121    {
122        self.tcp_keepalive_retries = retries.into();
123        self
124    }
125
126    /// Set the Linux-family `TCP_USER_TIMEOUT`.
127    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
128    #[cfg_attr(
129        docsrs,
130        doc(cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux")))
131    )]
132    pub fn tcp_user_timeout<D>(mut self, value: D) -> Self
133    where
134        D: Into<Option<Duration>>,
135    {
136        self.tcp_user_timeout = value.into();
137        self
138    }
139
140    /// Set the TCP send buffer size.
141    pub fn tcp_send_buffer_size<S>(mut self, size: S) -> Self
142    where
143        S: Into<Option<usize>>,
144    {
145        self.tcp_send_buffer_size = size.into();
146        self
147    }
148
149    /// Set the TCP receive buffer size.
150    pub fn tcp_recv_buffer_size<S>(mut self, size: S) -> Self
151    where
152        S: Into<Option<usize>>,
153    {
154        self.tcp_recv_buffer_size = size.into();
155        self
156    }
157
158    /// Set the Happy Eyeballs fallback timeout.
159    pub fn tcp_happy_eyeballs_timeout<D>(mut self, value: D) -> Self
160    where
161        D: Into<Option<Duration>>,
162    {
163        self.tcp_happy_eyeballs_timeout = value.into();
164        self
165    }
166
167    /// Replace the low-level TCP connect options.
168    pub fn tcp_connect_options(mut self, options: TcpConnectOptions) -> Self {
169        self.tcp_connect_options = options;
170        self
171    }
172}
173
174/// Reusable connection-pool settings for a [`crate::ClientBuilder`].
175#[must_use]
176#[derive(Clone)]
177pub struct PoolConfigOptions {
178    pub(crate) idle_timeout: Option<Duration>,
179    pub(crate) max_idle_per_host: usize,
180    pub(crate) max_size: Option<NonZeroU32>,
181}
182
183impl Default for PoolConfigOptions {
184    fn default() -> Self {
185        Self {
186            idle_timeout: Some(Duration::from_secs(90)),
187            max_idle_per_host: usize::MAX,
188            max_size: None,
189        }
190    }
191}
192
193impl PoolConfigOptions {
194    /// Create a pool config with the client defaults.
195    pub fn new() -> Self {
196        Self::default()
197    }
198
199    /// Set the idle timeout for pooled connections.
200    pub fn idle_timeout<D>(mut self, value: D) -> Self
201    where
202        D: Into<Option<Duration>>,
203    {
204        self.idle_timeout = value.into();
205        self
206    }
207
208    /// Set the maximum idle connections per host.
209    pub fn max_idle_per_host(mut self, max: usize) -> Self {
210        self.max_idle_per_host = max;
211        self
212    }
213
214    /// Set the maximum pool size.
215    pub fn max_size(mut self, max: Option<u32>) -> Self {
216        self.max_size = max.and_then(NonZeroU32::new);
217        self
218    }
219}
220
221/// Reusable TLS settings for a [`crate::ClientBuilder`].
222#[must_use]
223#[derive(Clone)]
224pub struct TlsConfigOptions {
225    pub(crate) keylog: Option<KeyLog>,
226    pub(crate) tls_info: bool,
227    pub(crate) tls_sni: bool,
228    pub(crate) verify_hostname: bool,
229    pub(crate) identity: Option<Identity>,
230    pub(crate) cert_store: CertStore,
231    pub(crate) cert_verification: bool,
232    pub(crate) min_version: Option<TlsVersion>,
233    pub(crate) max_version: Option<TlsVersion>,
234}
235
236impl Default for TlsConfigOptions {
237    fn default() -> Self {
238        Self {
239            keylog: None,
240            tls_info: false,
241            tls_sni: true,
242            verify_hostname: true,
243            identity: None,
244            cert_store: CertStore::default(),
245            cert_verification: true,
246            min_version: None,
247            max_version: None,
248        }
249    }
250}
251
252impl TlsConfigOptions {
253    /// Create a TLS config with the client defaults.
254    pub fn new() -> Self {
255        Self::default()
256    }
257
258    /// Set the client identity used for mutual TLS.
259    pub fn identity(mut self, identity: Identity) -> Self {
260        self.identity = Some(identity);
261        self
262    }
263
264    /// Replace the certificate store.
265    pub fn cert_store(mut self, store: CertStore) -> Self {
266        self.cert_store = store;
267        self
268    }
269
270    /// Enable or disable certificate verification.
271    pub fn cert_verification(mut self, enabled: bool) -> Self {
272        self.cert_verification = enabled;
273        self
274    }
275
276    /// Enable or disable hostname verification.
277    pub fn verify_hostname(mut self, enabled: bool) -> Self {
278        self.verify_hostname = enabled;
279        self
280    }
281
282    /// Enable or disable SNI.
283    pub fn tls_sni(mut self, enabled: bool) -> Self {
284        self.tls_sni = enabled;
285        self
286    }
287
288    /// Enable TLS info extensions on responses.
289    pub fn tls_info(mut self, enabled: bool) -> Self {
290        self.tls_info = enabled;
291        self
292    }
293
294    /// Configure TLS key logging.
295    pub fn keylog(mut self, keylog: KeyLog) -> Self {
296        self.keylog = Some(keylog);
297        self
298    }
299
300    /// Set the minimum TLS version.
301    pub fn min_tls_version(mut self, version: TlsVersion) -> Self {
302        self.min_version = Some(version);
303        self
304    }
305
306    /// Set the maximum TLS version.
307    pub fn max_tls_version(mut self, version: TlsVersion) -> Self {
308        self.max_version = Some(version);
309        self
310    }
311}
312
313/// Reusable HTTP protocol settings for a [`crate::ClientBuilder`].
314#[must_use]
315#[derive(Clone)]
316pub struct ProtocolConfigOptions {
317    pub(crate) http_version_preference: HttpVersionPreference,
318    pub(crate) https_only: bool,
319    pub(crate) retry_policy: retry::Policy,
320    pub(crate) redirect_policy: redirect::Policy,
321    pub(crate) referer: bool,
322    pub(crate) timeout_options: TimeoutOptions,
323    pub(crate) recoveries: Recoveries,
324}
325
326impl Default for ProtocolConfigOptions {
327    fn default() -> Self {
328        Self {
329            http_version_preference: HttpVersionPreference::All,
330            https_only: false,
331            retry_policy: retry::Policy::default(),
332            redirect_policy: redirect::Policy::none(),
333            referer: true,
334            timeout_options: TimeoutOptions::default(),
335            recoveries: Recoveries::new(),
336        }
337    }
338}
339
340impl ProtocolConfigOptions {
341    /// Create a protocol config with the client defaults.
342    pub fn new() -> Self {
343        Self::default()
344    }
345
346    /// Set the preferred HTTP version.
347    pub fn http_version_preference(mut self, preference: HttpVersionPreference) -> Self {
348        self.http_version_preference = preference;
349        self
350    }
351
352    /// Restrict the client to HTTPS requests only.
353    pub fn https_only(mut self, enabled: bool) -> Self {
354        self.https_only = enabled;
355        self
356    }
357
358    /// Set the retry policy.
359    pub fn retry_policy(mut self, policy: retry::Policy) -> Self {
360        self.retry_policy = policy;
361        self
362    }
363
364    /// Set the redirect policy.
365    pub fn redirect_policy(mut self, policy: redirect::Policy) -> Self {
366        self.redirect_policy = policy;
367        self
368    }
369
370    /// Enable or disable automatic referer propagation.
371    pub fn referer(mut self, enabled: bool) -> Self {
372        self.referer = enabled;
373        self
374    }
375
376    /// Replace the grouped timeout settings.
377    pub fn timeout_options(mut self, options: TimeoutOptions) -> Self {
378        self.timeout_options = options;
379        self
380    }
381
382    /// Replace the grouped recovery hooks.
383    pub fn recoveries(mut self, recoveries: Recoveries) -> Self {
384        self.recoveries = recoveries;
385        self
386    }
387}
388
389/// Reusable proxy settings for a [`crate::ClientBuilder`].
390#[must_use]
391#[derive(Clone)]
392pub struct ProxyConfigOptions {
393    pub(crate) proxies: Vec<Proxy>,
394    pub(crate) auto_system_proxy: bool,
395}
396
397impl Default for ProxyConfigOptions {
398    fn default() -> Self {
399        Self::new()
400    }
401}
402
403impl ProxyConfigOptions {
404    /// Create a proxy config with the client defaults.
405    pub fn new() -> Self {
406        Self {
407            proxies: Vec::new(),
408            auto_system_proxy: true,
409        }
410    }
411
412    /// Enable or disable automatic system proxy detection.
413    pub fn system_proxy(mut self, enabled: bool) -> Self {
414        self.auto_system_proxy = enabled;
415        self
416    }
417
418    /// Add a proxy rule.
419    pub fn proxy(mut self, proxy: Proxy) -> Self {
420        self.proxies.push(proxy);
421        self.auto_system_proxy = false;
422        self
423    }
424
425    /// Replace the proxy list.
426    pub fn proxies<I>(mut self, proxies: I) -> Self
427    where
428        I: IntoIterator<Item = Proxy>,
429    {
430        self.proxies = proxies.into_iter().collect();
431        self.auto_system_proxy = false;
432        self
433    }
434
435    /// Clear all proxy rules and disable system proxy detection.
436    pub fn no_proxy(mut self) -> Self {
437        self.proxies.clear();
438        self.auto_system_proxy = false;
439        self
440    }
441}