Skip to main content

reqwest/blocking/
client.rs

1#[cfg(any(feature = "__native-tls", feature = "__rustls",))]
2use std::any::Any;
3use std::convert::TryInto;
4use std::fmt;
5use std::future::Future;
6use std::net::IpAddr;
7use std::net::SocketAddr;
8use std::sync::Arc;
9use std::task::{ready, Poll};
10use std::thread;
11use std::time::Duration;
12
13use http::header::HeaderValue;
14use log::{error, trace};
15use tokio::sync::{mpsc, oneshot};
16use tower::Layer;
17use tower::Service;
18
19use super::request::{Request, RequestBuilder};
20use super::response::Response;
21use super::wait;
22use crate::connect::sealed::{Conn, Unnameable};
23#[cfg(unix)]
24use crate::connect::uds::UnixSocketProvider;
25use crate::connect::BoxedConnectorService;
26use crate::dns::Resolve;
27use crate::error::BoxError;
28#[cfg(feature = "__tls")]
29use crate::tls;
30#[cfg(feature = "__rustls")]
31use crate::tls::CertificateRevocationList;
32#[cfg(feature = "__tls")]
33use crate::Certificate;
34#[cfg(any(feature = "__native-tls", feature = "__rustls"))]
35use crate::Identity;
36use crate::{async_impl, header, redirect, IntoUrl, Method, Proxy};
37
38/// A `Client` to make Requests with.
39///
40/// The Client has various configuration values to tweak, but the defaults
41/// are set to what is usually the most commonly desired value. To configure a
42/// `Client`, use `Client::builder()`.
43///
44/// The `Client` holds a connection pool internally, so it is advised that
45/// you create one and **reuse** it.
46///
47/// # Examples
48///
49/// ```rust
50/// use reqwest::blocking::Client;
51/// #
52/// # fn run() -> Result<(), reqwest::Error> {
53/// let client = Client::new();
54/// let resp = client.get("http://httpbin.org/").send()?;
55/// #   drop(resp);
56/// #   Ok(())
57/// # }
58///
59/// ```
60#[derive(Clone)]
61pub struct Client {
62    inner: ClientHandle,
63}
64
65/// A `ClientBuilder` can be used to create a `Client` with  custom configuration.
66///
67/// # Example
68///
69/// ```
70/// # fn run() -> Result<(), reqwest::Error> {
71/// use std::time::Duration;
72///
73/// let client = reqwest::blocking::Client::builder()
74///     .timeout(Duration::from_secs(10))
75///     .build()?;
76/// # Ok(())
77/// # }
78/// ```
79#[must_use]
80pub struct ClientBuilder {
81    inner: async_impl::ClientBuilder,
82    timeout: Timeout,
83}
84
85impl Default for ClientBuilder {
86    fn default() -> Self {
87        Self::new()
88    }
89}
90
91impl ClientBuilder {
92    /// Constructs a new `ClientBuilder`.
93    ///
94    /// This is the same as `Client::builder()`.
95    pub fn new() -> Self {
96        ClientBuilder {
97            inner: async_impl::ClientBuilder::new(),
98            timeout: Timeout::default(),
99        }
100    }
101}
102
103impl ClientBuilder {
104    /// Returns a `Client` that uses this `ClientBuilder` configuration.
105    ///
106    /// # Errors
107    ///
108    /// This method fails if TLS backend cannot be initialized, or the resolver
109    /// cannot load the system configuration.
110    ///
111    /// # Panics
112    ///
113    /// This method panics if called from within an async runtime. See docs on
114    /// [`reqwest::blocking`][crate::blocking] for details.
115    pub fn build(self) -> crate::Result<Client> {
116        ClientHandle::new(self).map(|handle| Client { inner: handle })
117    }
118
119    // Higher-level options
120
121    /// Sets the `User-Agent` header to be used by this client.
122    ///
123    /// # Example
124    ///
125    /// ```rust
126    /// # fn doc() -> Result<(), reqwest::Error> {
127    /// // Name your user agent after your app?
128    /// static APP_USER_AGENT: &str = concat!(
129    ///     env!("CARGO_PKG_NAME"),
130    ///     "/",
131    ///     env!("CARGO_PKG_VERSION"),
132    /// );
133    ///
134    /// let client = reqwest::blocking::Client::builder()
135    ///     .user_agent(APP_USER_AGENT)
136    ///     .build()?;
137    /// let res = client.get("https://www.rust-lang.org").send()?;
138    /// # Ok(())
139    /// # }
140    /// ```
141    pub fn user_agent<V>(self, value: V) -> ClientBuilder
142    where
143        V: TryInto<HeaderValue>,
144        V::Error: Into<http::Error>,
145    {
146        self.with_inner(move |inner| inner.user_agent(value))
147    }
148
149    /// Sets the default headers for every request.
150    ///
151    /// # Example
152    ///
153    /// ```rust
154    /// use reqwest::header;
155    /// # fn build_client() -> Result<(), reqwest::Error> {
156    /// let mut headers = header::HeaderMap::new();
157    /// headers.insert("X-MY-HEADER", header::HeaderValue::from_static("value"));
158    /// headers.insert(header::AUTHORIZATION, header::HeaderValue::from_static("secret"));
159    ///
160    /// // Consider marking security-sensitive headers with `set_sensitive`.
161    /// let mut auth_value = header::HeaderValue::from_static("secret");
162    /// auth_value.set_sensitive(true);
163    /// headers.insert(header::AUTHORIZATION, auth_value);
164    ///
165    /// // get a client builder
166    /// let client = reqwest::blocking::Client::builder()
167    ///     .default_headers(headers)
168    ///     .build()?;
169    /// let res = client.get("https://www.rust-lang.org").send()?;
170    /// # Ok(())
171    /// # }
172    /// ```
173    pub fn default_headers(self, headers: header::HeaderMap) -> ClientBuilder {
174        self.with_inner(move |inner| inner.default_headers(headers))
175    }
176
177    /// Enable a persistent cookie store for the client.
178    ///
179    /// Cookies received in responses will be preserved and included in
180    /// additional requests.
181    ///
182    /// By default, no cookie store is used.
183    ///
184    /// # Optional
185    ///
186    /// This requires the optional `cookies` feature to be enabled.
187    #[cfg(feature = "cookies")]
188    #[cfg_attr(docsrs, doc(cfg(feature = "cookies")))]
189    pub fn cookie_store(self, enable: bool) -> ClientBuilder {
190        self.with_inner(|inner| inner.cookie_store(enable))
191    }
192
193    /// Set the persistent cookie store for the client.
194    ///
195    /// Cookies received in responses will be passed to this store, and
196    /// additional requests will query this store for cookies.
197    ///
198    /// By default, no cookie store is used.
199    ///
200    /// # Optional
201    ///
202    /// This requires the optional `cookies` feature to be enabled.
203    #[cfg(feature = "cookies")]
204    #[cfg_attr(docsrs, doc(cfg(feature = "cookies")))]
205    pub fn cookie_provider<C: crate::cookie::CookieStore + 'static>(
206        self,
207        cookie_store: Arc<C>,
208    ) -> ClientBuilder {
209        self.with_inner(|inner| inner.cookie_provider(cookie_store))
210    }
211
212    /// Enable auto gzip decompression by checking the `Content-Encoding` response header.
213    ///
214    /// If auto gzip decompression is turned on:
215    ///
216    /// - When sending a request and if the request's headers do not already contain
217    ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `gzip`.
218    ///   The request body is **not** automatically compressed.
219    /// - When receiving a response, if it's headers contain a `Content-Encoding` value that
220    ///   equals to `gzip`, both values `Content-Encoding` and `Content-Length` are removed from the
221    ///   headers' set. The response body is automatically decompressed.
222    ///
223    /// If the `gzip` feature is turned on, the default option is enabled.
224    ///
225    /// # Optional
226    ///
227    /// This requires the optional `gzip` feature to be enabled
228    #[cfg(feature = "gzip")]
229    #[cfg_attr(docsrs, doc(cfg(feature = "gzip")))]
230    pub fn gzip(self, enable: bool) -> ClientBuilder {
231        self.with_inner(|inner| inner.gzip(enable))
232    }
233
234    /// Enable auto brotli decompression by checking the `Content-Encoding` response header.
235    ///
236    /// If auto brotli decompression is turned on:
237    ///
238    /// - When sending a request and if the request's headers do not already contain
239    ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `br`.
240    ///   The request body is **not** automatically compressed.
241    /// - When receiving a response, if it's headers contain a `Content-Encoding` value that
242    ///   equals to `br`, both values `Content-Encoding` and `Content-Length` are removed from the
243    ///   headers' set. The response body is automatically decompressed.
244    ///
245    /// If the `brotli` feature is turned on, the default option is enabled.
246    ///
247    /// # Optional
248    ///
249    /// This requires the optional `brotli` feature to be enabled
250    #[cfg(feature = "brotli")]
251    #[cfg_attr(docsrs, doc(cfg(feature = "brotli")))]
252    pub fn brotli(self, enable: bool) -> ClientBuilder {
253        self.with_inner(|inner| inner.brotli(enable))
254    }
255
256    /// Enable auto zstd decompression by checking the `Content-Encoding` response header.
257    ///
258    /// If auto zstd decompression is turned on:
259    ///
260    /// - When sending a request and if the request's headers do not already contain
261    ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `zstd`.
262    ///   The request body is **not** automatically compressed.
263    /// - When receiving a response, if its headers contain a `Content-Encoding` value of
264    ///   `zstd`, both `Content-Encoding` and `Content-Length` are removed from the
265    ///   headers' set. The response body is automatically decompressed.
266    ///
267    /// If the `zstd` feature is turned on, the default option is enabled.
268    ///
269    /// # Optional
270    ///
271    /// This requires the optional `zstd` feature to be enabled
272    #[cfg(feature = "zstd")]
273    #[cfg_attr(docsrs, doc(cfg(feature = "zstd")))]
274    pub fn zstd(self, enable: bool) -> ClientBuilder {
275        self.with_inner(|inner| inner.zstd(enable))
276    }
277
278    /// Enable auto deflate decompression by checking the `Content-Encoding` response header.
279    ///
280    /// If auto deflate decompression is turned on:
281    ///
282    /// - When sending a request and if the request's headers do not already contain
283    ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `deflate`.
284    ///   The request body is **not** automatically compressed.
285    /// - When receiving a response, if it's headers contain a `Content-Encoding` value that
286    ///   equals to `deflate`, both values `Content-Encoding` and `Content-Length` are removed from the
287    ///   headers' set. The response body is automatically decompressed.
288    ///
289    /// If the `deflate` feature is turned on, the default option is enabled.
290    ///
291    /// # Optional
292    ///
293    /// This requires the optional `deflate` feature to be enabled
294    #[cfg(feature = "deflate")]
295    #[cfg_attr(docsrs, doc(cfg(feature = "deflate")))]
296    pub fn deflate(self, enable: bool) -> ClientBuilder {
297        self.with_inner(|inner| inner.deflate(enable))
298    }
299
300    /// Disable auto response body gzip decompression.
301    ///
302    /// This method exists even if the optional `gzip` feature is not enabled.
303    /// This can be used to ensure a `Client` doesn't use gzip decompression
304    /// even if another dependency were to enable the optional `gzip` feature.
305    pub fn no_gzip(self) -> ClientBuilder {
306        self.with_inner(|inner| inner.no_gzip())
307    }
308
309    /// Disable auto response body brotli decompression.
310    ///
311    /// This method exists even if the optional `brotli` feature is not enabled.
312    /// This can be used to ensure a `Client` doesn't use brotli decompression
313    /// even if another dependency were to enable the optional `brotli` feature.
314    pub fn no_brotli(self) -> ClientBuilder {
315        self.with_inner(|inner| inner.no_brotli())
316    }
317
318    /// Disable auto response body zstd decompression.
319    ///
320    /// This method exists even if the optional `zstd` feature is not enabled.
321    /// This can be used to ensure a `Client` doesn't use zstd decompression
322    /// even if another dependency were to enable the optional `zstd` feature.
323    pub fn no_zstd(self) -> ClientBuilder {
324        self.with_inner(|inner| inner.no_zstd())
325    }
326
327    /// Disable auto response body deflate decompression.
328    ///
329    /// This method exists even if the optional `deflate` feature is not enabled.
330    /// This can be used to ensure a `Client` doesn't use deflate decompression
331    /// even if another dependency were to enable the optional `deflate` feature.
332    pub fn no_deflate(self) -> ClientBuilder {
333        self.with_inner(|inner| inner.no_deflate())
334    }
335
336    // Redirect options
337
338    /// Set a `redirect::Policy` for this client.
339    ///
340    /// Default will follow redirects up to a maximum of 10.
341    pub fn redirect(self, policy: redirect::Policy) -> ClientBuilder {
342        self.with_inner(move |inner| inner.redirect(policy))
343    }
344
345    /// Set a request retry policy.
346    ///
347    /// Default behavior is to retry protocol NACKs.
348    pub fn retry(self, policy: crate::retry::Builder) -> ClientBuilder {
349        self.with_inner(move |inner| inner.retry(policy))
350    }
351
352    /// Enable or disable automatic setting of the `Referer` header.
353    ///
354    /// Default is `true`.
355    pub fn referer(self, enable: bool) -> ClientBuilder {
356        self.with_inner(|inner| inner.referer(enable))
357    }
358
359    // Proxy options
360
361    /// Add a `Proxy` to the list of proxies the `Client` will use.
362    ///
363    /// # Note
364    ///
365    /// Adding a proxy will disable the automatic usage of the "system" proxy.
366    pub fn proxy(self, proxy: Proxy) -> ClientBuilder {
367        self.with_inner(move |inner| inner.proxy(proxy))
368    }
369
370    /// Clear all `Proxies`, so `Client` will use no proxy anymore.
371    ///
372    /// # Note
373    /// To add a proxy exclusion list, use [Proxy::no_proxy()]
374    /// on all desired proxies instead.
375    ///
376    /// This also disables the automatic usage of the "system" proxy.
377    pub fn no_proxy(self) -> ClientBuilder {
378        self.with_inner(move |inner| inner.no_proxy())
379    }
380
381    // Timeout options
382
383    /// Set a timeout for connect, read and write operations of a `Client`.
384    ///
385    /// Default is 30 seconds.
386    ///
387    /// Pass `None` to disable timeout.
388    pub fn timeout<T>(mut self, timeout: T) -> ClientBuilder
389    where
390        T: Into<Option<Duration>>,
391    {
392        self.timeout = Timeout(timeout.into());
393        self
394    }
395
396    /// Set a timeout for only the connect phase of a `Client`.
397    ///
398    /// Default is `None`.
399    pub fn connect_timeout<T>(self, timeout: T) -> ClientBuilder
400    where
401        T: Into<Option<Duration>>,
402    {
403        let timeout = timeout.into();
404        if let Some(dur) = timeout {
405            self.with_inner(|inner| inner.connect_timeout(dur))
406        } else {
407            self
408        }
409    }
410
411    /// Set whether connections should emit verbose logs.
412    ///
413    /// Enabling this option will emit [log][] messages at the `TRACE` level
414    /// for read and write operations on connections.
415    ///
416    /// [log]: https://crates.io/crates/log
417    pub fn connection_verbose(self, verbose: bool) -> ClientBuilder {
418        self.with_inner(move |inner| inner.connection_verbose(verbose))
419    }
420
421    // HTTP options
422
423    /// Set an optional timeout for idle sockets being kept-alive.
424    ///
425    /// Pass `None` to disable timeout.
426    ///
427    /// Default is 90 seconds.
428    pub fn pool_idle_timeout<D>(self, val: D) -> ClientBuilder
429    where
430        D: Into<Option<Duration>>,
431    {
432        self.with_inner(|inner| inner.pool_idle_timeout(val))
433    }
434
435    /// Sets the maximum idle connection per host allowed in the pool.
436    pub fn pool_max_idle_per_host(self, max: usize) -> ClientBuilder {
437        self.with_inner(move |inner| inner.pool_max_idle_per_host(max))
438    }
439
440    /// Send headers as title case instead of lowercase.
441    pub fn http1_title_case_headers(self) -> ClientBuilder {
442        self.with_inner(|inner| inner.http1_title_case_headers())
443    }
444
445    /// Set whether HTTP/1 connections will accept obsolete line folding for
446    /// header values.
447    ///
448    /// Newline codepoints (`\r` and `\n`) will be transformed to spaces when
449    /// parsing.
450    pub fn http1_allow_obsolete_multiline_headers_in_responses(self, value: bool) -> ClientBuilder {
451        self.with_inner(|inner| inner.http1_allow_obsolete_multiline_headers_in_responses(value))
452    }
453
454    /// Sets whether invalid header lines should be silently ignored in HTTP/1 responses.
455    pub fn http1_ignore_invalid_headers_in_responses(self, value: bool) -> ClientBuilder {
456        self.with_inner(|inner| inner.http1_ignore_invalid_headers_in_responses(value))
457    }
458
459    /// Set whether HTTP/1 connections will accept spaces between header
460    /// names and the colon that follow them in responses.
461    ///
462    /// Newline codepoints (\r and \n) will be transformed to spaces when
463    /// parsing.
464    pub fn http1_allow_spaces_after_header_name_in_responses(self, value: bool) -> ClientBuilder {
465        self.with_inner(|inner| inner.http1_allow_spaces_after_header_name_in_responses(value))
466    }
467
468    /// Set the maximum number of headers accepted in an HTTP/1 response.
469    ///
470    /// When a response contains more headers than this value, it is rejected
471    /// with a parse error and the request fails.
472    ///
473    /// Default is 100.
474    pub fn http1_max_headers(self, max: usize) -> ClientBuilder {
475        self.with_inner(|inner| inner.http1_max_headers(max))
476    }
477
478    /// Only use HTTP/1.
479    pub fn http1_only(self) -> ClientBuilder {
480        self.with_inner(|inner| inner.http1_only())
481    }
482
483    /// Allow HTTP/0.9 responses
484    pub fn http09_responses(self) -> ClientBuilder {
485        self.with_inner(|inner| inner.http09_responses())
486    }
487
488    /// Only use HTTP/2.
489    #[cfg(feature = "http2")]
490    #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
491    pub fn http2_prior_knowledge(self) -> ClientBuilder {
492        self.with_inner(|inner| inner.http2_prior_knowledge())
493    }
494
495    /// Sets the `SETTINGS_INITIAL_WINDOW_SIZE` option for HTTP2 stream-level flow control.
496    ///
497    /// Default may change internally to optimize for common uses.
498    #[cfg(feature = "http2")]
499    #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
500    pub fn http2_initial_stream_window_size(self, sz: impl Into<Option<u32>>) -> ClientBuilder {
501        self.with_inner(|inner| inner.http2_initial_stream_window_size(sz))
502    }
503
504    /// Sets the max connection-level flow control for HTTP2
505    ///
506    /// Default may change internally to optimize for common uses.
507    #[cfg(feature = "http2")]
508    #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
509    pub fn http2_initial_connection_window_size(self, sz: impl Into<Option<u32>>) -> ClientBuilder {
510        self.with_inner(|inner| inner.http2_initial_connection_window_size(sz))
511    }
512
513    /// Sets whether to use an adaptive flow control.
514    ///
515    /// Enabling this will override the limits set in `http2_initial_stream_window_size` and
516    /// `http2_initial_connection_window_size`.
517    #[cfg(feature = "http2")]
518    #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
519    pub fn http2_adaptive_window(self, enabled: bool) -> ClientBuilder {
520        self.with_inner(|inner| inner.http2_adaptive_window(enabled))
521    }
522
523    /// Sets the maximum frame size to use for HTTP2.
524    ///
525    /// Default is currently 16,384 but may change internally to optimize for common uses.
526    #[cfg(feature = "http2")]
527    #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
528    pub fn http2_max_frame_size(self, sz: impl Into<Option<u32>>) -> ClientBuilder {
529        self.with_inner(|inner| inner.http2_max_frame_size(sz))
530    }
531
532    /// Sets the maximum size of received header frames for HTTP2.
533    ///
534    /// Default is currently 16KB, but can change.
535    #[cfg(feature = "http2")]
536    #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
537    pub fn http2_max_header_list_size(self, max_header_size_bytes: u32) -> ClientBuilder {
538        self.with_inner(|inner| inner.http2_max_header_list_size(max_header_size_bytes))
539    }
540
541    /// Sets an interval for HTTP2 Ping frames should be sent to keep a connection alive.
542    ///
543    /// Pass `None` to disable HTTP2 keep-alive.
544    /// Default is currently disabled.
545    #[cfg(feature = "http2")]
546    #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
547    pub fn http2_keep_alive_interval(self, interval: impl Into<Option<Duration>>) -> ClientBuilder {
548        self.with_inner(|inner| inner.http2_keep_alive_interval(interval))
549    }
550
551    /// Sets a timeout for receiving an acknowledgement of the keep-alive ping.
552    ///
553    /// If the ping is not acknowledged within the timeout, the connection will be closed.
554    /// Does nothing if `http2_keep_alive_interval` is disabled.
555    /// Default is currently disabled.
556    #[cfg(feature = "http2")]
557    #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
558    pub fn http2_keep_alive_timeout(self, timeout: Duration) -> ClientBuilder {
559        self.with_inner(|inner| inner.http2_keep_alive_timeout(timeout))
560    }
561
562    /// Sets whether HTTP2 keep-alive should apply while the connection is idle.
563    ///
564    /// If disabled, keep-alive pings are only sent while there are open request/responses streams.
565    /// If enabled, pings are also sent when no streams are active.
566    /// Does nothing if `http2_keep_alive_interval` is disabled.
567    /// Default is `false`.
568    #[cfg(feature = "http2")]
569    #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
570    pub fn http2_keep_alive_while_idle(self, enabled: bool) -> ClientBuilder {
571        self.with_inner(|inner| inner.http2_keep_alive_while_idle(enabled))
572    }
573
574    /// This requires the optional `http3` feature to be
575    /// enabled.
576    #[cfg(feature = "http3")]
577    #[cfg_attr(docsrs, doc(cfg(feature = "http3")))]
578    pub fn http3_prior_knowledge(self) -> ClientBuilder {
579        self.with_inner(|inner| inner.http3_prior_knowledge())
580    }
581
582    /// Maximum duration of inactivity to accept before timing out the QUIC connection.
583    ///
584    /// See the corresponding flow-control settings in [`quiche::Config`].
585    ///
586    /// [`quiche::Config`]: https://docs.rs/quiche/0.28.0/quiche/struct.Config.html
587    #[cfg(feature = "http3")]
588    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = "http3",))))]
589    pub fn http3_max_idle_timeout(self, value: Duration) -> ClientBuilder {
590        self.with_inner(|inner| inner.http3_max_idle_timeout(value))
591    }
592
593    /// Maximum number of bytes the peer may transmit without acknowledgement on any one stream
594    /// before becoming blocked.
595    ///
596    /// See the corresponding flow-control settings in [`quiche::Config`].
597    ///
598    /// [`quiche::Config`]: https://docs.rs/quiche/0.28.0/quiche/struct.Config.html
599    ///
600    /// # Panics
601    ///
602    /// Panics if the value is over 2^62.
603    #[cfg(feature = "http3")]
604    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = "http3",))))]
605    pub fn http3_stream_receive_window(self, value: u64) -> ClientBuilder {
606        self.with_inner(|inner| inner.http3_stream_receive_window(value))
607    }
608
609    /// Maximum number of bytes the peer may transmit across all streams of a connection before
610    /// becoming blocked.
611    ///
612    /// See the corresponding flow-control settings in [`quiche::Config`].
613    ///
614    /// [`quiche::Config`]: https://docs.rs/quiche/0.28.0/quiche/struct.Config.html
615    ///
616    /// # Panics
617    ///
618    /// Panics if the value is over 2^62.
619    #[cfg(feature = "http3")]
620    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = "http3",))))]
621    pub fn http3_conn_receive_window(self, value: u64) -> ClientBuilder {
622        self.with_inner(|inner| inner.http3_conn_receive_window(value))
623    }
624
625    /// Maximum number of bytes to transmit to a peer without acknowledgment
626    ///
627    /// See the corresponding flow-control settings in [`quiche::Config`].
628    ///
629    /// [`quiche::Config`]: https://docs.rs/quiche/0.28.0/quiche/struct.Config.html
630    #[cfg(feature = "http3")]
631    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = "http3",))))]
632    pub fn http3_send_window(self, value: u64) -> ClientBuilder {
633        self.with_inner(|inner| inner.http3_send_window(value))
634    }
635
636    /// Override the default congestion control algorithm to use [BBR]
637    ///
638    /// The current default congestion control algorithm is [CUBIC]. This method overrides the
639    /// default.
640    ///
641    /// [BBR]: https://datatracker.ietf.org/doc/html/draft-ietf-ccwg-bbr
642    /// [CUBIC]: https://datatracker.ietf.org/doc/html/rfc8312
643    #[cfg(feature = "http3")]
644    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = "http3",))))]
645    pub fn http3_congestion_bbr(self) -> ClientBuilder {
646        self.with_inner(|inner| inner.http3_congestion_bbr())
647    }
648
649    /// Set the maximum HTTP/3 header size this client is willing to accept.
650    ///
651    /// See [header size constraints] section of the specification for details.
652    ///
653    /// [header size constraints]: https://www.rfc-editor.org/rfc/rfc9114.html#name-header-size-constraints
654    ///
655    /// See the corresponding settings in [`quiche::h3::Config`].
656    ///
657    /// [`quiche::h3::Config`]: https://docs.rs/quiche/0.28.0/quiche/h3/struct.Config.html
658    #[cfg(feature = "http3")]
659    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = "http3",))))]
660    pub fn http3_max_field_section_size(self, value: u64) -> ClientBuilder {
661        self.with_inner(|inner| inner.http3_max_field_section_size(value))
662    }
663
664    /// Enable whether to send HTTP/3 protocol grease on the connections.
665    ///
666    /// HTTP/3 uses the concept of "grease"
667    ///
668    /// to prevent potential interoperability issues in the future.
669    /// In HTTP/3, the concept of grease is used to ensure that the protocol can evolve
670    /// and accommodate future changes without breaking existing implementations.
671    ///
672    /// See the corresponding settings in [`quiche::h3::Config`].
673    ///
674    /// [`quiche::h3::Config`]: https://docs.rs/quiche/0.28.0/quiche/h3/struct.Config.html
675    #[cfg(feature = "http3")]
676    #[cfg_attr(docsrs, doc(cfg(all(reqwest_unstable, feature = "http3",))))]
677    pub fn http3_send_grease(self, enabled: bool) -> ClientBuilder {
678        self.with_inner(|inner| inner.http3_send_grease(enabled))
679    }
680
681    // TCP options
682
683    /// Set whether sockets have `TCP_NODELAY` enabled.
684    ///
685    /// Default is `true`.
686    pub fn tcp_nodelay(self, enabled: bool) -> ClientBuilder {
687        self.with_inner(move |inner| inner.tcp_nodelay(enabled))
688    }
689
690    /// Bind to a local IP Address.
691    ///
692    /// # Example
693    ///
694    /// ```
695    /// use std::net::IpAddr;
696    /// let local_addr = IpAddr::from([12, 4, 1, 8]);
697    /// let client = reqwest::blocking::Client::builder()
698    ///     .local_address(local_addr)
699    ///     .build().unwrap();
700    /// ```
701    pub fn local_address<T>(self, addr: T) -> ClientBuilder
702    where
703        T: Into<Option<IpAddr>>,
704    {
705        self.with_inner(move |inner| inner.local_address(addr))
706    }
707
708    /// Bind to an interface by `SO_BINDTODEVICE`.
709    ///
710    /// # Example
711    ///
712    /// ```
713    /// let interface = "lo";
714    /// let client = reqwest::blocking::Client::builder()
715    ///     .interface(interface)
716    ///     .build().unwrap();
717    /// ```
718    #[cfg(any(
719        target_os = "android",
720        target_os = "fuchsia",
721        target_os = "illumos",
722        target_os = "ios",
723        target_os = "linux",
724        target_os = "macos",
725        target_os = "solaris",
726        target_os = "tvos",
727        target_os = "visionos",
728        target_os = "watchos",
729    ))]
730    pub fn interface(self, interface: &str) -> ClientBuilder {
731        self.with_inner(move |inner| inner.interface(interface))
732    }
733
734    /// Set that all sockets have `SO_KEEPALIVE` set with the supplied duration.
735    ///
736    /// If `None`, the option will not be set.
737    pub fn tcp_keepalive<D>(self, val: D) -> ClientBuilder
738    where
739        D: Into<Option<Duration>>,
740    {
741        self.with_inner(move |inner| inner.tcp_keepalive(val))
742    }
743
744    /// Set that all sockets have `SO_KEEPALIVE` set with the supplied interval.
745    ///
746    /// If `None`, the option will not be set.
747    pub fn tcp_keepalive_interval<D>(self, val: D) -> ClientBuilder
748    where
749        D: Into<Option<Duration>>,
750    {
751        self.with_inner(move |inner| inner.tcp_keepalive_interval(val))
752    }
753
754    /// Set that all sockets have `SO_KEEPALIVE` set with the supplied retry count.
755    ///
756    /// If `None`, the option will not be set.
757    pub fn tcp_keepalive_retries<C>(self, retries: C) -> ClientBuilder
758    where
759        C: Into<Option<u32>>,
760    {
761        self.with_inner(move |inner| inner.tcp_keepalive_retries(retries))
762    }
763
764    /// Set that all sockets have `TCP_USER_TIMEOUT` set with the supplied duration.
765    ///
766    /// This option controls how long transmitted data may remain unacknowledged before
767    /// the connection is force-closed.
768    ///
769    /// The current default is `None` (option disabled).
770    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
771    pub fn tcp_user_timeout<D>(self, val: D) -> ClientBuilder
772    where
773        D: Into<Option<Duration>>,
774    {
775        self.with_inner(move |inner| inner.tcp_user_timeout(val))
776    }
777
778    // Alt Transports
779
780    /// Set that all connections will use this Unix socket.
781    ///
782    /// If a request URI uses the `https` scheme, TLS will still be used over
783    /// the Unix socket.
784    ///
785    /// # Note
786    ///
787    /// This option is not compatible with any of the TCP or Proxy options.
788    /// Setting this will ignore all those options previously set.
789    ///
790    /// Likewise, DNS resolution will not be done on the domain name.
791    #[cfg(unix)]
792    pub fn unix_socket(self, path: impl UnixSocketProvider) -> ClientBuilder {
793        self.with_inner(move |inner| inner.unix_socket(path))
794    }
795
796    // TLS options
797
798    /// Add custom root certificates.
799    ///
800    /// This allows connecting to a server that has a self-signed
801    /// certificate for example. This **does not** replace the existing
802    /// trusted store.
803    ///
804    /// # Example
805    ///
806    /// ```
807    /// # use std::fs::File;
808    /// # use std::io::Read;
809    /// # fn build_client() -> Result<(), Box<dyn std::error::Error>> {
810    /// // read a local binary DER encoded certificate
811    /// let der = std::fs::read("my-cert.der")?;
812    ///
813    /// // create a certificate
814    /// let cert = reqwest::Certificate::from_der(&der)?;
815    ///
816    /// // get a client builder
817    /// let client = reqwest::blocking::Client::builder()
818    ///     .tls_certs_merge([cert])
819    ///     .build()?;
820    /// # drop(client);
821    /// # Ok(())
822    /// # }
823    /// ```
824    ///
825    /// # Optional
826    ///
827    /// This requires the optional `default-tls`, `native-tls`, or `boring` (or its legacy `rustls` aliases)
828    /// feature to be enabled.
829    #[cfg(feature = "__tls")]
830    #[cfg_attr(
831        docsrs,
832        doc(cfg(any(feature = "default-tls", feature = "native-tls", feature = "rustls")))
833    )]
834    pub fn tls_certs_merge(self, certs: impl IntoIterator<Item = Certificate>) -> ClientBuilder {
835        self.with_inner(move |inner| inner.tls_certs_merge(certs))
836    }
837
838    /// Use only the provided certificate roots.
839    ///
840    /// This can be used to connect to a server that has a self-signed
841    /// certificate for example.
842    ///
843    /// This option disables any native or built-in roots, and **only** uses
844    /// the roots provided to this method.
845    ///
846    /// # Optional
847    ///
848    /// This requires the optional `default-tls`, `native-tls`, or `boring` (or its legacy `rustls` aliases)
849    /// feature to be enabled.
850    #[cfg(feature = "__tls")]
851    #[cfg_attr(
852        docsrs,
853        doc(cfg(any(feature = "default-tls", feature = "native-tls", feature = "rustls")))
854    )]
855    pub fn tls_certs_only(self, certs: impl IntoIterator<Item = Certificate>) -> ClientBuilder {
856        self.with_inner(move |inner| inner.tls_certs_only(certs))
857    }
858
859    /// Deprecated: use [`ClientBuilder::tls_certs_merge()`] or [`ClientBuilder::tls_certs_only()`] instead.
860    #[cfg(feature = "__tls")]
861    pub fn add_root_certificate(self, cert: Certificate) -> ClientBuilder {
862        self.with_inner(move |inner| inner.add_root_certificate(cert))
863    }
864
865    /// Add multiple certificate revocation lists.
866    ///
867    /// # Errors
868    ///
869    /// This only works if also using only provided root certificates. This
870    /// cannot work with the native verifier.
871    ///
872    /// If CRLs are added but `tls_certs_only()` is not called, the builder
873    /// will return an error.
874    ///
875    /// # Optional
876    ///
877    /// This requires the `boring` (or its legacy `rustls` aliases) Cargo feature enabled.
878    #[cfg(feature = "__rustls")]
879    #[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
880    pub fn tls_crls_only(
881        self,
882        crls: impl IntoIterator<Item = CertificateRevocationList>,
883    ) -> ClientBuilder {
884        self.with_inner(move |inner| inner.tls_crls_only(crls))
885    }
886
887    /// Deprecated: use [`ClientBuilder::tls_crls_only()`] instead.
888    #[cfg(feature = "__rustls")]
889    #[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
890    pub fn add_crl(self, crl: CertificateRevocationList) -> ClientBuilder {
891        self.with_inner(move |inner| inner.add_crl(crl))
892    }
893
894    /// Deprecated: use [`ClientBuilder::tls_crls_only()`] instead.
895    #[cfg(feature = "__rustls")]
896    #[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
897    pub fn add_crls(
898        self,
899        crls: impl IntoIterator<Item = CertificateRevocationList>,
900    ) -> ClientBuilder {
901        self.with_inner(move |inner| inner.add_crls(crls))
902    }
903
904    /// Sets the identity to be used for client certificate authentication.
905    ///
906    /// # Optional
907    ///
908    /// This requires the optional `native-tls` or `boring` (or its legacy `rustls` aliases) feature to be
909    /// enabled.
910    #[cfg(any(feature = "__native-tls", feature = "__rustls"))]
911    #[cfg_attr(docsrs, doc(cfg(any(feature = "native-tls", feature = "rustls"))))]
912    pub fn identity(self, identity: Identity) -> ClientBuilder {
913        self.with_inner(move |inner| inner.identity(identity))
914    }
915
916    /// Controls the use of hostname verification.
917    ///
918    /// Defaults to `false`.
919    ///
920    /// # Warning
921    ///
922    /// You should think very carefully before you use this method. If
923    /// hostname verification is not used, any valid certificate for any
924    /// site will be trusted for use from any other. This introduces a
925    /// significant vulnerability to man-in-the-middle attacks.
926    ///
927    /// # Errors
928    ///
929    /// Depending on the TLS backend and verifier, this might not work with
930    /// native certificates, only those added with [`ClientBuilder::tls_certs_only()`].
931    ///
932    /// # Optional
933    ///
934    /// This requires the optional `default-tls`, `native-tls`, or `boring` (or its legacy `rustls` aliases)
935    /// feature to be enabled.
936    #[cfg(feature = "__tls")]
937    #[cfg_attr(
938        docsrs,
939        doc(cfg(any(feature = "default-tls", feature = "native-tls", feature = "rustls")))
940    )]
941    pub fn tls_danger_accept_invalid_hostnames(
942        self,
943        accept_invalid_hostname: bool,
944    ) -> ClientBuilder {
945        self.with_inner(|inner| inner.tls_danger_accept_invalid_hostnames(accept_invalid_hostname))
946    }
947
948    /// Deprecated: use [`ClientBuilder::tls_danger_accept_invalid_hostnames()`] instead.
949    #[cfg(feature = "__tls")]
950    pub fn danger_accept_invalid_hostnames(self, accept_invalid_hostname: bool) -> ClientBuilder {
951        self.with_inner(|inner| inner.danger_accept_invalid_hostnames(accept_invalid_hostname))
952    }
953
954    /// Controls the use of certificate validation.
955    ///
956    /// Defaults to `false`.
957    ///
958    /// # Warning
959    ///
960    /// You should think very carefully before using this method. If
961    /// invalid certificates are trusted, *any* certificate for *any* site
962    /// will be trusted for use. This includes expired certificates. This
963    /// introduces significant vulnerabilities, and should only be used
964    /// as a last resort.
965    #[cfg(feature = "__tls")]
966    #[cfg_attr(
967        docsrs,
968        doc(cfg(any(feature = "default-tls", feature = "native-tls", feature = "rustls")))
969    )]
970    pub fn tls_danger_accept_invalid_certs(self, accept_invalid_certs: bool) -> ClientBuilder {
971        self.with_inner(|inner| inner.tls_danger_accept_invalid_certs(accept_invalid_certs))
972    }
973
974    /// Deprecated: use [`ClientBuilder::tls_danger_accept_invalid_certs()`] instead.
975    #[cfg(feature = "__tls")]
976    pub fn danger_accept_invalid_certs(self, accept_invalid_certs: bool) -> ClientBuilder {
977        self.with_inner(|inner| inner.danger_accept_invalid_certs(accept_invalid_certs))
978    }
979
980    /// Controls the use of TLS server name indication.
981    ///
982    /// Defaults to `true`.
983    #[cfg(feature = "__tls")]
984    #[cfg_attr(
985        docsrs,
986        doc(cfg(any(feature = "default-tls", feature = "native-tls", feature = "rustls")))
987    )]
988    pub fn tls_sni(self, tls_sni: bool) -> ClientBuilder {
989        self.with_inner(|inner| inner.tls_sni(tls_sni))
990    }
991
992    /// Controls if the SSLKEYLOGFILE environment variable is respected.
993    ///
994    /// When enabled, if the environment variable `SSLKEYLOGFILE` is present at runtime,
995    /// TLS keys will be logged to the file at the path described in the variable.
996    /// This can be used by end-users to allow debugging TLS connections.
997    ///
998    /// Defaults to `false`.
999    ///
1000    /// # Optional
1001    ///
1002    /// This requires the `boring` (or its legacy `rustls` aliases) Cargo feature enabled.
1003    #[cfg(feature = "__rustls")]
1004    #[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
1005    pub fn tls_sslkeylogfile(self, on: bool) -> ClientBuilder {
1006        self.with_inner(|inner| inner.tls_sslkeylogfile(on))
1007    }
1008
1009    /// Set the minimum required TLS version for connections.
1010    ///
1011    /// By default, the TLS backend's own default is used.
1012    ///
1013    /// # Errors
1014    ///
1015    /// A value of `tls::Version::TLS_1_3` will cause an error with the
1016    /// `native-tls` backend. This does not mean the version
1017    /// isn't supported, just that it can't be set as a minimum due to
1018    /// technical limitations.
1019    ///
1020    /// # Optional
1021    ///
1022    /// This requires the optional `default-tls`, `native-tls`, or `boring` (or its legacy `rustls` aliases)
1023    /// feature to be enabled.
1024    #[cfg(feature = "__tls")]
1025    #[cfg_attr(
1026        docsrs,
1027        doc(cfg(any(feature = "default-tls", feature = "native-tls", feature = "rustls")))
1028    )]
1029    pub fn tls_version_min(self, version: tls::Version) -> ClientBuilder {
1030        self.with_inner(|inner| inner.tls_version_min(version))
1031    }
1032
1033    /// Deprecated: use [`ClientBuilder::tls_version_min()`] instead.
1034    #[cfg(feature = "__tls")]
1035    pub fn min_tls_version(self, version: tls::Version) -> ClientBuilder {
1036        self.with_inner(|inner| inner.min_tls_version(version))
1037    }
1038
1039    /// Set the maximum allowed TLS version for connections.
1040    ///
1041    /// By default, there's no maximum.
1042    ///
1043    /// # Errors
1044    ///
1045    /// A value of `tls::Version::TLS_1_3` will cause an error with the
1046    /// `native-tls` backend. This does not mean the version
1047    /// isn't supported, just that it can't be set as a maximum due to
1048    /// technical limitations.
1049    ///
1050    /// # Optional
1051    ///
1052    /// This requires the optional `default-tls`, `native-tls`, or `boring` (or its legacy `rustls` aliases)
1053    /// feature to be enabled.
1054    #[cfg(feature = "__tls")]
1055    #[cfg_attr(
1056        docsrs,
1057        doc(cfg(any(feature = "default-tls", feature = "native-tls", feature = "rustls")))
1058    )]
1059    pub fn tls_version_max(self, version: tls::Version) -> ClientBuilder {
1060        self.with_inner(|inner| inner.tls_version_max(version))
1061    }
1062
1063    /// Deprecated: use [`ClientBuilder::tls_version_max()`] instead.
1064    #[cfg(feature = "__tls")]
1065    pub fn max_tls_version(self, version: tls::Version) -> ClientBuilder {
1066        self.with_inner(|inner| inner.max_tls_version(version))
1067    }
1068
1069    /// Force using the native TLS backend.
1070    ///
1071    /// Since multiple TLS backends can be optionally enabled, this option will
1072    /// force the `native-tls` backend to be used for this `Client`.
1073    ///
1074    /// # Optional
1075    ///
1076    /// This requires the optional `native-tls` feature to be enabled.
1077    #[cfg(feature = "__native-tls")]
1078    #[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))]
1079    pub fn tls_backend_native(self) -> ClientBuilder {
1080        self.with_inner(move |inner| inner.tls_backend_native())
1081    }
1082
1083    /// Deprecated: use [`ClientBuilder::tls_backend_native()`] instead.
1084    #[cfg(feature = "__native-tls")]
1085    pub fn use_native_tls(self) -> ClientBuilder {
1086        self.with_inner(move |inner| inner.use_native_tls())
1087    }
1088
1089    /// Force using the Rustls TLS backend.
1090    ///
1091    /// Since multiple TLS backends can be optionally enabled, this option will
1092    /// force the BoringSSL backend (the method name is retained for compatibility) to be used for this `Client`.
1093    ///
1094    /// # Optional
1095    ///
1096    /// This requires the optional `boring` (or its legacy `rustls` aliases) feature to be enabled.
1097    #[cfg(feature = "__rustls")]
1098    #[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
1099    pub fn tls_backend_rustls(self) -> ClientBuilder {
1100        self.with_inner(move |inner| inner.tls_backend_rustls())
1101    }
1102
1103    /// Deprecated: use [`ClientBuilder::tls_backend_rustls()`] instead.
1104    #[cfg(feature = "__rustls")]
1105    #[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
1106    pub fn use_rustls_tls(self) -> ClientBuilder {
1107        self.with_inner(move |inner| inner.use_rustls_tls())
1108    }
1109
1110    /// Add TLS information as `TlsInfo` extension to responses.
1111    ///
1112    /// # Optional
1113    ///
1114    /// This requires the optional `default-tls`, `native-tls`, or `boring` (or its legacy `rustls` aliases)
1115    /// feature to be enabled.
1116    #[cfg(feature = "__tls")]
1117    #[cfg_attr(
1118        docsrs,
1119        doc(cfg(any(feature = "default-tls", feature = "native-tls", feature = "rustls")))
1120    )]
1121    pub fn tls_info(self, tls_info: bool) -> ClientBuilder {
1122        self.with_inner(|inner| inner.tls_info(tls_info))
1123    }
1124
1125    /// Use a preconfigured TLS backend.
1126    ///
1127    /// If the passed `Any` argument is not a TLS backend that reqwest
1128    /// understands, the `ClientBuilder` will error when calling `build`.
1129    ///
1130    /// # Advanced
1131    ///
1132    /// This is an advanced option, and can be somewhat brittle. Usage requires
1133    /// keeping the preconfigured TLS argument version in sync with reqwest,
1134    /// since version mismatches will result in an "unknown" TLS backend.
1135    ///
1136    /// If possible, it's preferable to use the methods on `ClientBuilder`
1137    /// to configure reqwest's TLS.
1138    ///
1139    /// # Optional
1140    ///
1141    /// This requires one of the optional features `native-tls` or
1142    /// `boring` (or its legacy `rustls` aliases) to be enabled.
1143    #[cfg(any(feature = "__native-tls", feature = "__rustls",))]
1144    #[cfg_attr(docsrs, doc(cfg(any(feature = "native-tls", feature = "rustls"))))]
1145    pub fn tls_backend_preconfigured(self, tls: impl Any) -> ClientBuilder {
1146        self.with_inner(move |inner| inner.tls_backend_preconfigured(tls))
1147    }
1148
1149    /// Deprecated: use [`ClientBuilder::tls_backend_preconfigured()`] instead.
1150    #[cfg(any(feature = "__native-tls", feature = "__rustls",))]
1151    pub fn use_preconfigured_tls(self, tls: impl Any) -> ClientBuilder {
1152        self.with_inner(move |inner| inner.use_preconfigured_tls(tls))
1153    }
1154
1155    /// Enables the [hickory-dns](hickory_resolver) async resolver instead of a default threadpool using `getaddrinfo`.
1156    ///
1157    /// If the `hickory-dns` feature is turned on, the default option is enabled.
1158    ///
1159    /// # Optional
1160    ///
1161    /// This requires the optional `hickory-dns` feature to be enabled
1162    #[cfg(feature = "hickory-dns")]
1163    #[cfg_attr(docsrs, doc(cfg(feature = "hickory-dns")))]
1164    pub fn hickory_dns(self, enable: bool) -> ClientBuilder {
1165        self.with_inner(|inner| inner.hickory_dns(enable))
1166    }
1167
1168    /// Disables the hickory-dns async resolver.
1169    ///
1170    /// This method exists even if the optional `hickory-dns` feature is not enabled.
1171    /// This can be used to ensure a `Client` doesn't use the hickory-dns async resolver
1172    /// even if another dependency were to enable the optional `hickory-dns` feature.
1173    pub fn no_hickory_dns(self) -> ClientBuilder {
1174        self.with_inner(|inner| inner.no_hickory_dns())
1175    }
1176
1177    /// Restrict the Client to be used with HTTPS only requests.
1178    ///
1179    /// Defaults to false.
1180    pub fn https_only(self, enabled: bool) -> ClientBuilder {
1181        self.with_inner(|inner| inner.https_only(enabled))
1182    }
1183
1184    /// Override DNS resolution for specific domains to a particular IP address.
1185    ///
1186    /// Set the port to `0` to use the conventional port for the given scheme (e.g. 80 for http).
1187    /// Ports in the URL itself will always be used instead of the port in the overridden addr.
1188    pub fn resolve(self, domain: &str, addr: SocketAddr) -> ClientBuilder {
1189        self.resolve_to_addrs(domain, &[addr])
1190    }
1191
1192    /// Override DNS resolution for specific domains to particular IP addresses.
1193    ///
1194    /// Set the port to `0` to use the conventional port for the given scheme (e.g. 80 for http).
1195    /// Ports in the URL itself will always be used instead of the port in the overridden addr.
1196    pub fn resolve_to_addrs(self, domain: &str, addrs: &[SocketAddr]) -> ClientBuilder {
1197        self.with_inner(|inner| inner.resolve_to_addrs(domain, addrs))
1198    }
1199
1200    /// Override the DNS resolver implementation.
1201    ///
1202    /// Pass an `Arc` wrapping a trait object implementing `Resolve`.
1203    /// Overrides for specific names passed to `resolve` and `resolve_to_addrs` will
1204    /// still be applied on top of this resolver.
1205    pub fn dns_resolver<R: Resolve + 'static>(self, resolver: Arc<R>) -> ClientBuilder {
1206        self.with_inner(|inner| inner.dns_resolver(resolver))
1207    }
1208
1209    /// Adds a new Tower [`Layer`](https://docs.rs/tower/latest/tower/trait.Layer.html) to the
1210    /// base connector [`Service`](https://docs.rs/tower/latest/tower/trait.Service.html) which
1211    /// is responsible for connection establishment.
1212    ///
1213    /// Each subsequent invocation of this function will wrap previous layers.
1214    ///
1215    /// Example usage:
1216    /// ```
1217    /// use std::time::Duration;
1218    ///
1219    /// let client = reqwest::blocking::Client::builder()
1220    ///                      // resolved to outermost layer, meaning while we are waiting on concurrency limit
1221    ///                      .connect_timeout(Duration::from_millis(200))
1222    ///                      // underneath the concurrency check, so only after concurrency limit lets us through
1223    ///                      .connector_layer(tower::timeout::TimeoutLayer::new(Duration::from_millis(50)))
1224    ///                      .connector_layer(tower::limit::concurrency::ConcurrencyLimitLayer::new(2))
1225    ///                      .build()
1226    ///                      .unwrap();
1227    /// ```
1228    pub fn connector_layer<L>(self, layer: L) -> ClientBuilder
1229    where
1230        L: Layer<BoxedConnectorService> + Clone + Send + Sync + 'static,
1231        L::Service:
1232            Service<Unnameable, Response = Conn, Error = BoxError> + Clone + Send + Sync + 'static,
1233        <L::Service as Service<Unnameable>>::Future: Send + 'static,
1234    {
1235        self.with_inner(|inner| inner.connector_layer(layer))
1236    }
1237
1238    // private
1239
1240    fn with_inner<F>(mut self, func: F) -> ClientBuilder
1241    where
1242        F: FnOnce(async_impl::ClientBuilder) -> async_impl::ClientBuilder,
1243    {
1244        self.inner = func(self.inner);
1245        self
1246    }
1247}
1248
1249impl From<async_impl::ClientBuilder> for ClientBuilder {
1250    fn from(builder: async_impl::ClientBuilder) -> Self {
1251        Self {
1252            inner: builder,
1253            timeout: Timeout::default(),
1254        }
1255    }
1256}
1257
1258impl Default for Client {
1259    fn default() -> Self {
1260        Self::new()
1261    }
1262}
1263
1264impl Client {
1265    /// Constructs a new `Client`.
1266    ///
1267    /// # Panic
1268    ///
1269    /// This method panics if TLS backend cannot be initialized, or the resolver
1270    /// cannot load the system configuration.
1271    ///
1272    /// Use `Client::builder()` if you wish to handle the failure as an `Error`
1273    /// instead of panicking.
1274    ///
1275    /// This method also panics if called from within an async runtime. See docs
1276    /// on [`reqwest::blocking`][crate::blocking] for details.
1277    pub fn new() -> Client {
1278        ClientBuilder::new().build().expect("Client::new()")
1279    }
1280
1281    /// Creates a `ClientBuilder` to configure a `Client`.
1282    ///
1283    /// This is the same as `ClientBuilder::new()`.
1284    pub fn builder() -> ClientBuilder {
1285        ClientBuilder::new()
1286    }
1287
1288    /// Convenience method to make a `GET` request to a URL.
1289    ///
1290    /// # Errors
1291    ///
1292    /// This method fails whenever supplied `Url` cannot be parsed.
1293    pub fn get<U: IntoUrl>(&self, url: U) -> RequestBuilder {
1294        self.request(Method::GET, url)
1295    }
1296
1297    /// Convenience method to make a `POST` request to a URL.
1298    ///
1299    /// # Errors
1300    ///
1301    /// This method fails whenever supplied `Url` cannot be parsed.
1302    pub fn post<U: IntoUrl>(&self, url: U) -> RequestBuilder {
1303        self.request(Method::POST, url)
1304    }
1305
1306    /// Convenience method to make a `PUT` request to a URL.
1307    ///
1308    /// # Errors
1309    ///
1310    /// This method fails whenever supplied `Url` cannot be parsed.
1311    pub fn put<U: IntoUrl>(&self, url: U) -> RequestBuilder {
1312        self.request(Method::PUT, url)
1313    }
1314
1315    /// Convenience method to make a `PATCH` request to a URL.
1316    ///
1317    /// # Errors
1318    ///
1319    /// This method fails whenever supplied `Url` cannot be parsed.
1320    pub fn patch<U: IntoUrl>(&self, url: U) -> RequestBuilder {
1321        self.request(Method::PATCH, url)
1322    }
1323
1324    /// Convenience method to make a `DELETE` request to a URL.
1325    ///
1326    /// # Errors
1327    ///
1328    /// This method fails whenever supplied `Url` cannot be parsed.
1329    pub fn delete<U: IntoUrl>(&self, url: U) -> RequestBuilder {
1330        self.request(Method::DELETE, url)
1331    }
1332
1333    /// Convenience method to make a `HEAD` request to a URL.
1334    ///
1335    /// # Errors
1336    ///
1337    /// This method fails whenever supplied `Url` cannot be parsed.
1338    pub fn head<U: IntoUrl>(&self, url: U) -> RequestBuilder {
1339        self.request(Method::HEAD, url)
1340    }
1341
1342    /// Start building a `Request` with the `Method` and `Url`.
1343    ///
1344    /// Returns a `RequestBuilder`, which will allow setting headers and
1345    /// request body before sending.
1346    ///
1347    /// # Errors
1348    ///
1349    /// This method fails whenever supplied `Url` cannot be parsed.
1350    pub fn request<U: IntoUrl>(&self, method: Method, url: U) -> RequestBuilder {
1351        let req = url.into_url().map(move |url| Request::new(method, url));
1352        RequestBuilder::new(self.clone(), req)
1353    }
1354
1355    /// Executes a `Request`.
1356    ///
1357    /// A `Request` can be built manually with `Request::new()` or obtained
1358    /// from a RequestBuilder with `RequestBuilder::build()`.
1359    ///
1360    /// You should prefer to use the `RequestBuilder` and
1361    /// `RequestBuilder::send()`.
1362    ///
1363    /// # Errors
1364    ///
1365    /// This method fails if there was an error while sending request,
1366    /// or redirect limit was exhausted.
1367    pub fn execute(&self, request: Request) -> crate::Result<Response> {
1368        self.inner.execute_request(request)
1369    }
1370}
1371
1372impl fmt::Debug for Client {
1373    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1374        f.debug_struct("Client")
1375            //.field("gzip", &self.inner.gzip)
1376            //.field("redirect_policy", &self.inner.redirect_policy)
1377            //.field("referer", &self.inner.referer)
1378            .finish()
1379    }
1380}
1381
1382impl fmt::Debug for ClientBuilder {
1383    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1384        self.inner.fmt(f)
1385    }
1386}
1387
1388#[derive(Clone)]
1389struct ClientHandle {
1390    timeout: Timeout,
1391    inner: Arc<InnerClientHandle>,
1392}
1393
1394type OneshotResponse = oneshot::Sender<crate::Result<async_impl::Response>>;
1395type ThreadSender = mpsc::UnboundedSender<(async_impl::Request, OneshotResponse)>;
1396
1397struct InnerClientHandle {
1398    tx: Option<ThreadSender>,
1399    thread: Option<thread::JoinHandle<()>>,
1400}
1401
1402impl Drop for InnerClientHandle {
1403    fn drop(&mut self) {
1404        let id = self
1405            .thread
1406            .as_ref()
1407            .map(|h| h.thread().id())
1408            .expect("thread not dropped yet");
1409
1410        trace!("closing runtime thread ({id:?})");
1411        self.tx.take();
1412        trace!("signaled close for runtime thread ({id:?})");
1413        self.thread.take().map(|h| h.join());
1414        trace!("closed runtime thread ({id:?})");
1415    }
1416}
1417
1418impl ClientHandle {
1419    fn new(builder: ClientBuilder) -> crate::Result<ClientHandle> {
1420        let timeout = builder.timeout;
1421        let builder = builder.inner;
1422        let (tx, rx) = mpsc::unbounded_channel::<(async_impl::Request, OneshotResponse)>();
1423        let (spawn_tx, spawn_rx) = oneshot::channel::<crate::Result<()>>();
1424        let handle = thread::Builder::new()
1425            .name("reqwest-internal-sync-runtime".into())
1426            .spawn(move || {
1427                use tokio::runtime;
1428                let rt = match runtime::Builder::new_current_thread()
1429                    .enable_all()
1430                    .build()
1431                    .map_err(crate::error::builder)
1432                {
1433                    Err(e) => {
1434                        if let Err(e) = spawn_tx.send(Err(e)) {
1435                            error!("Failed to communicate runtime creation failure: {e:?}");
1436                        }
1437                        return;
1438                    }
1439                    Ok(v) => v,
1440                };
1441
1442                let f = async move {
1443                    let client = match builder.build() {
1444                        Err(e) => {
1445                            if let Err(e) = spawn_tx.send(Err(e)) {
1446                                error!("Failed to communicate client creation failure: {e:?}");
1447                            }
1448                            return;
1449                        }
1450                        Ok(v) => v,
1451                    };
1452                    if let Err(e) = spawn_tx.send(Ok(())) {
1453                        error!("Failed to communicate successful startup: {e:?}");
1454                        return;
1455                    }
1456
1457                    let mut rx = rx;
1458
1459                    while let Some((req, req_tx)) = rx.recv().await {
1460                        let req_fut = client.execute(req);
1461                        tokio::spawn(forward(req_fut, req_tx));
1462                    }
1463
1464                    trace!("({:?}) Receiver is shutdown", thread::current().id());
1465                };
1466
1467                trace!("({:?}) start runtime::block_on", thread::current().id());
1468                rt.block_on(f);
1469                trace!("({:?}) end runtime::block_on", thread::current().id());
1470                drop(rt);
1471                trace!("({:?}) finished", thread::current().id());
1472            })
1473            .map_err(crate::error::builder)?;
1474
1475        // Wait for the runtime thread to start up...
1476        match wait::timeout(spawn_rx, None) {
1477            Ok(Ok(())) => (),
1478            Ok(Err(err)) => return Err(err),
1479            Err(_canceled) => event_loop_panicked(),
1480        }
1481
1482        let inner_handle = Arc::new(InnerClientHandle {
1483            tx: Some(tx),
1484            thread: Some(handle),
1485        });
1486
1487        Ok(ClientHandle {
1488            timeout,
1489            inner: inner_handle,
1490        })
1491    }
1492
1493    fn execute_request(&self, req: Request) -> crate::Result<Response> {
1494        let (tx, rx) = oneshot::channel();
1495        let (req, body) = req.into_async();
1496        let url = req.url().clone();
1497        let timeout = req.timeout().copied().or(self.timeout.0);
1498
1499        self.inner
1500            .tx
1501            .as_ref()
1502            .expect("core thread exited early")
1503            .send((req, tx))
1504            .expect("core thread panicked");
1505
1506        let result: Result<crate::Result<async_impl::Response>, wait::Waited<crate::Error>> =
1507            if let Some(body) = body {
1508                let f = async move {
1509                    body.send().await?;
1510                    rx.await.map_err(|_canceled| event_loop_panicked())
1511                };
1512                wait::timeout(f, timeout)
1513            } else {
1514                let f = async move { rx.await.map_err(|_canceled| event_loop_panicked()) };
1515                wait::timeout(f, timeout)
1516            };
1517
1518        match result {
1519            Ok(Err(err)) => Err(err.with_url(url)),
1520            Ok(Ok(res)) => Ok(Response::new(
1521                res,
1522                timeout,
1523                KeepCoreThreadAlive(Some(self.inner.clone())),
1524            )),
1525            Err(wait::Waited::TimedOut(e)) => Err(crate::error::request(e).with_url(url)),
1526            Err(wait::Waited::Inner(err)) => Err(err.with_url(url)),
1527        }
1528    }
1529}
1530
1531async fn forward<F>(fut: F, mut tx: OneshotResponse)
1532where
1533    F: Future<Output = crate::Result<async_impl::Response>>,
1534{
1535    futures_util::pin_mut!(fut);
1536
1537    // "select" on the sender being canceled, and the future completing
1538    let res = std::future::poll_fn(|cx| {
1539        match fut.as_mut().poll(cx) {
1540            Poll::Ready(val) => Poll::Ready(Some(val)),
1541            Poll::Pending => {
1542                // check if the callback is canceled
1543                ready!(tx.poll_closed(cx));
1544                Poll::Ready(None)
1545            }
1546        }
1547    })
1548    .await;
1549
1550    if let Some(res) = res {
1551        let _ = tx.send(res);
1552    }
1553    // else request is canceled
1554}
1555
1556#[derive(Clone, Copy)]
1557struct Timeout(Option<Duration>);
1558
1559impl Default for Timeout {
1560    fn default() -> Timeout {
1561        // default mentioned in ClientBuilder::timeout() doc comment
1562        Timeout(Some(Duration::from_secs(30)))
1563    }
1564}
1565
1566pub(crate) struct KeepCoreThreadAlive(#[allow(dead_code)] Option<Arc<InnerClientHandle>>);
1567
1568impl KeepCoreThreadAlive {
1569    pub(crate) fn empty() -> KeepCoreThreadAlive {
1570        KeepCoreThreadAlive(None)
1571    }
1572}
1573
1574#[cold]
1575#[inline(never)]
1576fn event_loop_panicked() -> ! {
1577    // The only possible reason there would be a Canceled error
1578    // is if the thread running the event loop panicked. We could return
1579    // an Err here, like a BrokenPipe, but the Client is not
1580    // recoverable. Additionally, the panic in the other thread
1581    // is not normal, and should likely be propagated.
1582    panic!("event loop thread panicked");
1583}