reqwest_h3/async_impl/
client.rs

1#[cfg(any(feature = "native-tls", feature = "__rustls",))]
2use std::any::Any;
3use std::future::Future;
4use std::net::IpAddr;
5use std::pin::Pin;
6use std::sync::Arc;
7use std::task::{Context, Poll};
8use std::time::Duration;
9use std::{collections::HashMap, convert::TryInto, net::SocketAddr};
10use std::{fmt, str};
11
12use super::decoder::Accepts;
13use super::request::{Request, RequestBuilder};
14use super::response::Response;
15use super::Body;
16#[cfg(feature = "http3")]
17use crate::async_impl::h3_client::connect::H3Connector;
18#[cfg(feature = "http3")]
19use crate::async_impl::h3_client::{H3Client, H3ResponseFuture};
20use crate::connect::{
21    sealed::{Conn, Unnameable},
22    BoxedConnectorLayer, BoxedConnectorService, Connector, ConnectorBuilder,
23};
24#[cfg(feature = "cookies")]
25use crate::cookie;
26#[cfg(feature = "hickory-dns")]
27use crate::dns::hickory::HickoryDnsResolver;
28use crate::dns::{gai::GaiResolver, DnsResolverWithOverrides, DynResolver, Resolve};
29use crate::error::{self, BoxError};
30use crate::into_url::try_uri;
31use crate::redirect::{self, remove_sensitive_headers};
32#[cfg(feature = "__rustls")]
33use crate::tls::CertificateRevocationList;
34#[cfg(feature = "__tls")]
35use crate::tls::{self, TlsBackend};
36#[cfg(feature = "__tls")]
37use crate::Certificate;
38#[cfg(any(feature = "native-tls", feature = "__rustls"))]
39use crate::Identity;
40use crate::{IntoUrl, Method, Proxy, StatusCode, Url};
41use bytes::Bytes;
42use http::header::{
43    Entry, HeaderMap, HeaderValue, ACCEPT, ACCEPT_ENCODING, CONTENT_ENCODING, CONTENT_LENGTH,
44    CONTENT_TYPE, LOCATION, PROXY_AUTHORIZATION, RANGE, REFERER, TRANSFER_ENCODING, USER_AGENT,
45};
46use http::uri::Scheme;
47use http::Uri;
48use hyper_util::client::legacy::connect::HttpConnector;
49use log::debug;
50#[cfg(feature = "default-tls")]
51use native_tls_crate::TlsConnector;
52use pin_project_lite::pin_project;
53#[cfg(feature = "http3")]
54use quinn::TransportConfig;
55#[cfg(feature = "http3")]
56use quinn::VarInt;
57use tokio::time::Sleep;
58use tower::util::BoxCloneSyncServiceLayer;
59use tower::{Layer, Service};
60
61type HyperResponseFuture = hyper_util::client::legacy::ResponseFuture;
62
63/// An asynchronous `Client` to make Requests with.
64///
65/// The Client has various configuration values to tweak, but the defaults
66/// are set to what is usually the most commonly desired value. To configure a
67/// `Client`, use `Client::builder()`.
68///
69/// The `Client` holds a connection pool internally, so it is advised that
70/// you create one and **reuse** it.
71///
72/// You do **not** have to wrap the `Client` in an [`Rc`] or [`Arc`] to **reuse** it,
73/// because it already uses an [`Arc`] internally.
74///
75/// [`Rc`]: std::rc::Rc
76#[derive(Clone)]
77pub struct Client {
78    inner: Arc<ClientRef>,
79}
80
81/// A `ClientBuilder` can be used to create a `Client` with custom configuration.
82#[must_use]
83pub struct ClientBuilder {
84    config: Config,
85}
86
87enum HttpVersionPref {
88    Http1,
89    #[cfg(feature = "http2")]
90    Http2,
91    #[cfg(feature = "http3")]
92    Http3,
93    All,
94}
95
96struct Config {
97    // NOTE: When adding a new field, update `fmt::Debug for ClientBuilder`
98    accepts: Accepts,
99    headers: HeaderMap,
100    #[cfg(feature = "__tls")]
101    hostname_verification: bool,
102    #[cfg(feature = "__tls")]
103    certs_verification: bool,
104    #[cfg(feature = "__tls")]
105    tls_sni: bool,
106    connect_timeout: Option<Duration>,
107    connection_verbose: bool,
108    pool_idle_timeout: Option<Duration>,
109    pool_max_idle_per_host: usize,
110    tcp_keepalive: Option<Duration>,
111    #[cfg(any(feature = "native-tls", feature = "__rustls"))]
112    identity: Option<Identity>,
113    proxies: Vec<Proxy>,
114    auto_sys_proxy: bool,
115    redirect_policy: redirect::Policy,
116    referer: bool,
117    read_timeout: Option<Duration>,
118    timeout: Option<Duration>,
119    #[cfg(feature = "__tls")]
120    root_certs: Vec<Certificate>,
121    #[cfg(feature = "__tls")]
122    tls_built_in_root_certs: bool,
123    #[cfg(feature = "rustls-tls-webpki-roots-no-provider")]
124    tls_built_in_certs_webpki: bool,
125    #[cfg(feature = "rustls-tls-native-roots-no-provider")]
126    tls_built_in_certs_native: bool,
127    #[cfg(feature = "__rustls")]
128    crls: Vec<CertificateRevocationList>,
129    #[cfg(feature = "__tls")]
130    min_tls_version: Option<tls::Version>,
131    #[cfg(feature = "__tls")]
132    max_tls_version: Option<tls::Version>,
133    #[cfg(feature = "__tls")]
134    tls_info: bool,
135    #[cfg(feature = "__tls")]
136    tls: TlsBackend,
137    connector_layers: Vec<BoxedConnectorLayer>,
138    http_version_pref: HttpVersionPref,
139    http09_responses: bool,
140    http1_title_case_headers: bool,
141    http1_allow_obsolete_multiline_headers_in_responses: bool,
142    http1_ignore_invalid_headers_in_responses: bool,
143    http1_allow_spaces_after_header_name_in_responses: bool,
144    #[cfg(feature = "http2")]
145    http2_initial_stream_window_size: Option<u32>,
146    #[cfg(feature = "http2")]
147    http2_initial_connection_window_size: Option<u32>,
148    #[cfg(feature = "http2")]
149    http2_adaptive_window: bool,
150    #[cfg(feature = "http2")]
151    http2_max_frame_size: Option<u32>,
152    #[cfg(feature = "http2")]
153    http2_max_header_list_size: Option<u32>,
154    #[cfg(feature = "http2")]
155    http2_keep_alive_interval: Option<Duration>,
156    #[cfg(feature = "http2")]
157    http2_keep_alive_timeout: Option<Duration>,
158    #[cfg(feature = "http2")]
159    http2_keep_alive_while_idle: bool,
160    local_address: Option<IpAddr>,
161    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
162    interface: Option<String>,
163    nodelay: bool,
164    #[cfg(feature = "cookies")]
165    cookie_store: Option<Arc<dyn cookie::CookieStore>>,
166    hickory_dns: bool,
167    error: Option<crate::Error>,
168    https_only: bool,
169    #[cfg(feature = "http3")]
170    tls_enable_early_data: bool,
171    #[cfg(feature = "http3")]
172    quic_max_idle_timeout: Option<Duration>,
173    #[cfg(feature = "http3")]
174    quic_stream_receive_window: Option<VarInt>,
175    #[cfg(feature = "http3")]
176    quic_receive_window: Option<VarInt>,
177    #[cfg(feature = "http3")]
178    quic_send_window: Option<u64>,
179    dns_overrides: HashMap<String, Vec<SocketAddr>>,
180    dns_resolver: Option<Arc<dyn Resolve>>,
181}
182
183impl Default for ClientBuilder {
184    fn default() -> Self {
185        Self::new()
186    }
187}
188
189impl ClientBuilder {
190    /// Constructs a new `ClientBuilder`.
191    ///
192    /// This is the same as `Client::builder()`.
193    pub fn new() -> Self {
194        let mut headers: HeaderMap<HeaderValue> = HeaderMap::with_capacity(2);
195        headers.insert(ACCEPT, HeaderValue::from_static("*/*"));
196
197        ClientBuilder {
198            config: Config {
199                error: None,
200                accepts: Accepts::default(),
201                headers,
202                #[cfg(feature = "__tls")]
203                hostname_verification: true,
204                #[cfg(feature = "__tls")]
205                certs_verification: true,
206                #[cfg(feature = "__tls")]
207                tls_sni: true,
208                connect_timeout: None,
209                connection_verbose: false,
210                pool_idle_timeout: Some(Duration::from_secs(90)),
211                pool_max_idle_per_host: usize::MAX,
212                // TODO: Re-enable default duration once hyper's HttpConnector is fixed
213                // to no longer error when an option fails.
214                tcp_keepalive: None, //Some(Duration::from_secs(60)),
215                proxies: Vec::new(),
216                auto_sys_proxy: true,
217                redirect_policy: redirect::Policy::default(),
218                referer: true,
219                read_timeout: None,
220                timeout: None,
221                #[cfg(feature = "__tls")]
222                root_certs: Vec::new(),
223                #[cfg(feature = "__tls")]
224                tls_built_in_root_certs: true,
225                #[cfg(feature = "rustls-tls-webpki-roots-no-provider")]
226                tls_built_in_certs_webpki: true,
227                #[cfg(feature = "rustls-tls-native-roots-no-provider")]
228                tls_built_in_certs_native: true,
229                #[cfg(any(feature = "native-tls", feature = "__rustls"))]
230                identity: None,
231                #[cfg(feature = "__rustls")]
232                crls: vec![],
233                #[cfg(feature = "__tls")]
234                min_tls_version: None,
235                #[cfg(feature = "__tls")]
236                max_tls_version: None,
237                #[cfg(feature = "__tls")]
238                tls_info: false,
239                #[cfg(feature = "__tls")]
240                tls: TlsBackend::default(),
241                connector_layers: Vec::new(),
242                http_version_pref: HttpVersionPref::All,
243                http09_responses: false,
244                http1_title_case_headers: false,
245                http1_allow_obsolete_multiline_headers_in_responses: false,
246                http1_ignore_invalid_headers_in_responses: false,
247                http1_allow_spaces_after_header_name_in_responses: false,
248                #[cfg(feature = "http2")]
249                http2_initial_stream_window_size: None,
250                #[cfg(feature = "http2")]
251                http2_initial_connection_window_size: None,
252                #[cfg(feature = "http2")]
253                http2_adaptive_window: false,
254                #[cfg(feature = "http2")]
255                http2_max_frame_size: None,
256                #[cfg(feature = "http2")]
257                http2_max_header_list_size: None,
258                #[cfg(feature = "http2")]
259                http2_keep_alive_interval: None,
260                #[cfg(feature = "http2")]
261                http2_keep_alive_timeout: None,
262                #[cfg(feature = "http2")]
263                http2_keep_alive_while_idle: false,
264                local_address: None,
265                #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
266                interface: None,
267                nodelay: true,
268                hickory_dns: cfg!(feature = "hickory-dns"),
269                #[cfg(feature = "cookies")]
270                cookie_store: None,
271                https_only: false,
272                dns_overrides: HashMap::new(),
273                #[cfg(feature = "http3")]
274                tls_enable_early_data: false,
275                #[cfg(feature = "http3")]
276                quic_max_idle_timeout: None,
277                #[cfg(feature = "http3")]
278                quic_stream_receive_window: None,
279                #[cfg(feature = "http3")]
280                quic_receive_window: None,
281                #[cfg(feature = "http3")]
282                quic_send_window: None,
283                dns_resolver: None,
284            },
285        }
286    }
287}
288
289impl ClientBuilder {
290    /// Returns a `Client` that uses this `ClientBuilder` configuration.
291    ///
292    /// # Errors
293    ///
294    /// This method fails if a TLS backend cannot be initialized, or the resolver
295    /// cannot load the system configuration.
296    pub fn build(self) -> crate::Result<Client> {
297        let config = self.config;
298
299        if let Some(err) = config.error {
300            return Err(err);
301        }
302
303        let mut proxies = config.proxies;
304        if config.auto_sys_proxy {
305            proxies.push(Proxy::system());
306        }
307        let proxies = Arc::new(proxies);
308
309        #[allow(unused)]
310        #[cfg(feature = "http3")]
311        let mut h3_connector = None;
312
313        let mut connector_builder = {
314            #[cfg(feature = "__tls")]
315            fn user_agent(headers: &HeaderMap) -> Option<HeaderValue> {
316                headers.get(USER_AGENT).cloned()
317            }
318
319            let mut resolver: Arc<dyn Resolve> = match config.hickory_dns {
320                false => Arc::new(GaiResolver::new()),
321                #[cfg(feature = "hickory-dns")]
322                true => Arc::new(HickoryDnsResolver::default()),
323                #[cfg(not(feature = "hickory-dns"))]
324                true => unreachable!("hickory-dns shouldn't be enabled unless the feature is"),
325            };
326            if let Some(dns_resolver) = config.dns_resolver {
327                resolver = dns_resolver;
328            }
329            if !config.dns_overrides.is_empty() {
330                resolver = Arc::new(DnsResolverWithOverrides::new(
331                    resolver,
332                    config.dns_overrides,
333                ));
334            }
335            let mut http = HttpConnector::new_with_resolver(DynResolver::new(resolver.clone()));
336            http.set_connect_timeout(config.connect_timeout);
337
338            #[cfg(all(feature = "http3", feature = "__rustls"))]
339            let build_h3_connector =
340                |resolver,
341                 tls,
342                 quic_max_idle_timeout: Option<Duration>,
343                 quic_stream_receive_window,
344                 quic_receive_window,
345                 quic_send_window,
346                 local_address,
347                 http_version_pref: &HttpVersionPref| {
348                    let mut transport_config = TransportConfig::default();
349
350                    if let Some(max_idle_timeout) = quic_max_idle_timeout {
351                        transport_config.max_idle_timeout(Some(
352                            max_idle_timeout.try_into().map_err(error::builder)?,
353                        ));
354                    }
355
356                    if let Some(stream_receive_window) = quic_stream_receive_window {
357                        transport_config.stream_receive_window(stream_receive_window);
358                    }
359
360                    if let Some(receive_window) = quic_receive_window {
361                        transport_config.receive_window(receive_window);
362                    }
363
364                    if let Some(send_window) = quic_send_window {
365                        transport_config.send_window(send_window);
366                    }
367
368                    let res = H3Connector::new(
369                        DynResolver::new(resolver),
370                        tls,
371                        local_address,
372                        transport_config,
373                    );
374
375                    match res {
376                        Ok(connector) => Ok(Some(connector)),
377                        Err(err) => {
378                            if let HttpVersionPref::Http3 = http_version_pref {
379                                Err(error::builder(err))
380                            } else {
381                                Ok(None)
382                            }
383                        }
384                    }
385                };
386
387            #[cfg(feature = "__tls")]
388            match config.tls {
389                #[cfg(feature = "default-tls")]
390                TlsBackend::Default => {
391                    let mut tls = TlsConnector::builder();
392
393                    #[cfg(all(feature = "native-tls-alpn", not(feature = "http3")))]
394                    {
395                        match config.http_version_pref {
396                            HttpVersionPref::Http1 => {
397                                tls.request_alpns(&["http/1.1"]);
398                            }
399                            #[cfg(feature = "http2")]
400                            HttpVersionPref::Http2 => {
401                                tls.request_alpns(&["h2"]);
402                            }
403                            HttpVersionPref::All => {
404                                tls.request_alpns(&["h2", "http/1.1"]);
405                            }
406                        }
407                    }
408
409                    tls.danger_accept_invalid_hostnames(!config.hostname_verification);
410
411                    tls.danger_accept_invalid_certs(!config.certs_verification);
412
413                    tls.use_sni(config.tls_sni);
414
415                    tls.disable_built_in_roots(!config.tls_built_in_root_certs);
416
417                    for cert in config.root_certs {
418                        cert.add_to_native_tls(&mut tls);
419                    }
420
421                    #[cfg(feature = "native-tls")]
422                    {
423                        if let Some(id) = config.identity {
424                            id.add_to_native_tls(&mut tls)?;
425                        }
426                    }
427                    #[cfg(all(feature = "__rustls", not(feature = "native-tls")))]
428                    {
429                        // Default backend + rustls Identity doesn't work.
430                        if let Some(_id) = config.identity {
431                            return Err(crate::error::builder("incompatible TLS identity type"));
432                        }
433                    }
434
435                    if let Some(min_tls_version) = config.min_tls_version {
436                        let protocol = min_tls_version.to_native_tls().ok_or_else(|| {
437                            // TLS v1.3. This would be entirely reasonable,
438                            // native-tls just doesn't support it.
439                            // https://github.com/sfackler/rust-native-tls/issues/140
440                            crate::error::builder("invalid minimum TLS version for backend")
441                        })?;
442                        tls.min_protocol_version(Some(protocol));
443                    }
444
445                    if let Some(max_tls_version) = config.max_tls_version {
446                        let protocol = max_tls_version.to_native_tls().ok_or_else(|| {
447                            // TLS v1.3.
448                            // We could arguably do max_protocol_version(None), given
449                            // that 1.4 does not exist yet, but that'd get messy in the
450                            // future.
451                            crate::error::builder("invalid maximum TLS version for backend")
452                        })?;
453                        tls.max_protocol_version(Some(protocol));
454                    }
455
456                    ConnectorBuilder::new_default_tls(
457                        http,
458                        tls,
459                        proxies.clone(),
460                        user_agent(&config.headers),
461                        config.local_address,
462                        #[cfg(any(
463                            target_os = "android",
464                            target_os = "fuchsia",
465                            target_os = "linux"
466                        ))]
467                        config.interface.as_deref(),
468                        config.nodelay,
469                        config.tls_info,
470                    )?
471                }
472                #[cfg(feature = "native-tls")]
473                TlsBackend::BuiltNativeTls(conn) => ConnectorBuilder::from_built_default_tls(
474                    http,
475                    conn,
476                    proxies.clone(),
477                    user_agent(&config.headers),
478                    config.local_address,
479                    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
480                    config.interface.as_deref(),
481                    config.nodelay,
482                    config.tls_info,
483                ),
484                #[cfg(feature = "__rustls")]
485                TlsBackend::BuiltRustls(conn) => {
486                    #[cfg(feature = "http3")]
487                    {
488                        h3_connector = build_h3_connector(
489                            resolver,
490                            conn.clone(),
491                            config.quic_max_idle_timeout,
492                            config.quic_stream_receive_window,
493                            config.quic_receive_window,
494                            config.quic_send_window,
495                            config.local_address,
496                            &config.http_version_pref,
497                        )?;
498                    }
499
500                    ConnectorBuilder::new_rustls_tls(
501                        http,
502                        conn,
503                        proxies.clone(),
504                        user_agent(&config.headers),
505                        config.local_address,
506                        #[cfg(any(
507                            target_os = "android",
508                            target_os = "fuchsia",
509                            target_os = "linux"
510                        ))]
511                        config.interface.as_deref(),
512                        config.nodelay,
513                        config.tls_info,
514                    )
515                }
516                #[cfg(feature = "__rustls")]
517                TlsBackend::Rustls => {
518                    use crate::tls::{IgnoreHostname, NoVerifier};
519
520                    // Set root certificates.
521                    let mut root_cert_store = rustls::RootCertStore::empty();
522                    for cert in config.root_certs {
523                        cert.add_to_rustls(&mut root_cert_store)?;
524                    }
525
526                    #[cfg(feature = "rustls-tls-webpki-roots-no-provider")]
527                    if config.tls_built_in_certs_webpki {
528                        root_cert_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
529                    }
530
531                    #[cfg(feature = "rustls-tls-native-roots-no-provider")]
532                    if config.tls_built_in_certs_native {
533                        let mut valid_count = 0;
534                        let mut invalid_count = 0;
535
536                        let load_results = rustls_native_certs::load_native_certs();
537                        for cert in load_results.certs {
538                            // Continue on parsing errors, as native stores often include ancient or syntactically
539                            // invalid certificates, like root certificates without any X509 extensions.
540                            // Inspiration: https://github.com/rustls/rustls/blob/633bf4ba9d9521a95f68766d04c22e2b01e68318/rustls/src/anchors.rs#L105-L112
541                            match root_cert_store.add(cert.into()) {
542                                Ok(_) => valid_count += 1,
543                                Err(err) => {
544                                    invalid_count += 1;
545                                    log::debug!("rustls failed to parse DER certificate: {err:?}");
546                                }
547                            }
548                        }
549                        if valid_count == 0 && invalid_count > 0 {
550                            let err = if load_results.errors.is_empty() {
551                                crate::error::builder(
552                                    "zero valid certificates found in native root store",
553                                )
554                            } else {
555                                use std::fmt::Write as _;
556                                let mut acc = String::new();
557                                for err in load_results.errors {
558                                    let _ = writeln!(&mut acc, "{err}");
559                                }
560
561                                crate::error::builder(acc)
562                            };
563
564                            return Err(err);
565                        }
566                    }
567
568                    // Set TLS versions.
569                    let mut versions = rustls::ALL_VERSIONS.to_vec();
570
571                    if let Some(min_tls_version) = config.min_tls_version {
572                        versions.retain(|&supported_version| {
573                            match tls::Version::from_rustls(supported_version.version) {
574                                Some(version) => version >= min_tls_version,
575                                // Assume it's so new we don't know about it, allow it
576                                // (as of writing this is unreachable)
577                                None => true,
578                            }
579                        });
580                    }
581
582                    if let Some(max_tls_version) = config.max_tls_version {
583                        versions.retain(|&supported_version| {
584                            match tls::Version::from_rustls(supported_version.version) {
585                                Some(version) => version <= max_tls_version,
586                                None => false,
587                            }
588                        });
589                    }
590
591                    if versions.is_empty() {
592                        return Err(crate::error::builder("empty supported tls versions"));
593                    }
594
595                    // Allow user to have installed a runtime default.
596                    // If not, we use ring.
597                    let provider = rustls::crypto::CryptoProvider::get_default()
598                        .map(|arc| arc.clone())
599                        .unwrap_or_else(|| {
600                            #[cfg(not(feature = "__rustls-ring"))]
601                            panic!("No provider set");
602
603                            #[cfg(feature = "__rustls-ring")]
604                            Arc::new(rustls::crypto::ring::default_provider())
605                        });
606
607                    // Build TLS config
608                    let signature_algorithms = provider.signature_verification_algorithms;
609                    let config_builder =
610                        rustls::ClientConfig::builder_with_provider(provider.clone())
611                            .with_protocol_versions(&versions)
612                            .map_err(|_| crate::error::builder("invalid TLS versions"))?;
613
614                    let config_builder = if !config.certs_verification {
615                        config_builder
616                            .dangerous()
617                            .with_custom_certificate_verifier(Arc::new(NoVerifier))
618                    } else if !config.hostname_verification {
619                        config_builder
620                            .dangerous()
621                            .with_custom_certificate_verifier(Arc::new(IgnoreHostname::new(
622                                root_cert_store,
623                                signature_algorithms,
624                            )))
625                    } else {
626                        if config.crls.is_empty() {
627                            config_builder.with_root_certificates(root_cert_store)
628                        } else {
629                            let crls = config
630                                .crls
631                                .iter()
632                                .map(|e| e.as_rustls_crl())
633                                .collect::<Vec<_>>();
634                            let verifier =
635                                rustls::client::WebPkiServerVerifier::builder_with_provider(
636                                    Arc::new(root_cert_store),
637                                    provider,
638                                )
639                                .with_crls(crls)
640                                .build()
641                                .map_err(|_| {
642                                    crate::error::builder("invalid TLS verification settings")
643                                })?;
644                            config_builder.with_webpki_verifier(verifier)
645                        }
646                    };
647
648                    // Finalize TLS config
649                    let mut tls = if let Some(id) = config.identity {
650                        id.add_to_rustls(config_builder)?
651                    } else {
652                        config_builder.with_no_client_auth()
653                    };
654
655                    tls.enable_sni = config.tls_sni;
656
657                    // ALPN protocol
658                    match config.http_version_pref {
659                        HttpVersionPref::Http1 => {
660                            tls.alpn_protocols = vec!["http/1.1".into()];
661                        }
662
663                        #[cfg(feature = "http2")]
664                        HttpVersionPref::Http2 => {
665                            tls.alpn_protocols = vec!["h2".into()];
666                        }
667
668                        #[cfg(feature = "http3")]
669                        HttpVersionPref::Http3 => {
670                            tls.alpn_protocols = vec!["h3".into()];
671                        }
672
673                        HttpVersionPref::All => {
674                            tls.alpn_protocols = vec![
675                                #[cfg(feature = "http2")]
676                                "h2".into(),
677                                "http/1.1".into(),
678                            ];
679                        }
680                    }
681
682                    #[cfg(feature = "http3")]
683                    {
684                        tls.enable_early_data = config.tls_enable_early_data;
685
686                        h3_connector = build_h3_connector(
687                            resolver,
688                            tls.clone(),
689                            config.quic_max_idle_timeout,
690                            config.quic_stream_receive_window,
691                            config.quic_receive_window,
692                            config.quic_send_window,
693                            config.local_address,
694                            &config.http_version_pref,
695                        )?;
696                    }
697
698                    ConnectorBuilder::new_rustls_tls(
699                        http,
700                        tls,
701                        proxies.clone(),
702                        user_agent(&config.headers),
703                        config.local_address,
704                        #[cfg(any(
705                            target_os = "android",
706                            target_os = "fuchsia",
707                            target_os = "linux"
708                        ))]
709                        config.interface.as_deref(),
710                        config.nodelay,
711                        config.tls_info,
712                    )
713                }
714                #[cfg(any(feature = "native-tls", feature = "__rustls",))]
715                TlsBackend::UnknownPreconfigured => {
716                    return Err(crate::error::builder(
717                        "Unknown TLS backend passed to `use_preconfigured_tls`",
718                    ));
719                }
720            }
721
722            #[cfg(not(feature = "__tls"))]
723            ConnectorBuilder::new(
724                http,
725                proxies.clone(),
726                config.local_address,
727                #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
728                config.interface.as_deref(),
729                config.nodelay,
730            )
731        };
732
733        connector_builder.set_timeout(config.connect_timeout);
734        connector_builder.set_verbose(config.connection_verbose);
735        connector_builder.set_keepalive(config.tcp_keepalive);
736
737        let mut builder =
738            hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new());
739        #[cfg(feature = "http2")]
740        {
741            if matches!(config.http_version_pref, HttpVersionPref::Http2) {
742                builder.http2_only(true);
743            }
744
745            if let Some(http2_initial_stream_window_size) = config.http2_initial_stream_window_size
746            {
747                builder.http2_initial_stream_window_size(http2_initial_stream_window_size);
748            }
749            if let Some(http2_initial_connection_window_size) =
750                config.http2_initial_connection_window_size
751            {
752                builder.http2_initial_connection_window_size(http2_initial_connection_window_size);
753            }
754            if config.http2_adaptive_window {
755                builder.http2_adaptive_window(true);
756            }
757            if let Some(http2_max_frame_size) = config.http2_max_frame_size {
758                builder.http2_max_frame_size(http2_max_frame_size);
759            }
760            if let Some(http2_max_header_list_size) = config.http2_max_header_list_size {
761                builder.http2_max_header_list_size(http2_max_header_list_size);
762            }
763            if let Some(http2_keep_alive_interval) = config.http2_keep_alive_interval {
764                builder.http2_keep_alive_interval(http2_keep_alive_interval);
765            }
766            if let Some(http2_keep_alive_timeout) = config.http2_keep_alive_timeout {
767                builder.http2_keep_alive_timeout(http2_keep_alive_timeout);
768            }
769            if config.http2_keep_alive_while_idle {
770                builder.http2_keep_alive_while_idle(true);
771            }
772        }
773
774        builder.timer(hyper_util::rt::TokioTimer::new());
775        builder.pool_timer(hyper_util::rt::TokioTimer::new());
776        builder.pool_idle_timeout(config.pool_idle_timeout);
777        builder.pool_max_idle_per_host(config.pool_max_idle_per_host);
778
779        if config.http09_responses {
780            builder.http09_responses(true);
781        }
782
783        if config.http1_title_case_headers {
784            builder.http1_title_case_headers(true);
785        }
786
787        if config.http1_allow_obsolete_multiline_headers_in_responses {
788            builder.http1_allow_obsolete_multiline_headers_in_responses(true);
789        }
790
791        if config.http1_ignore_invalid_headers_in_responses {
792            builder.http1_ignore_invalid_headers_in_responses(true);
793        }
794
795        if config.http1_allow_spaces_after_header_name_in_responses {
796            builder.http1_allow_spaces_after_header_name_in_responses(true);
797        }
798
799        let proxies_maybe_http_auth = proxies.iter().any(|p| p.maybe_has_http_auth());
800
801        Ok(Client {
802            inner: Arc::new(ClientRef {
803                accepts: config.accepts,
804                #[cfg(feature = "cookies")]
805                cookie_store: config.cookie_store,
806
807                // Use match instead of map since config is partially moved
808                // and it cannot be used in closure
809                #[cfg(feature = "http3")]
810                h3_client: match h3_connector {
811                    Some(h3_connector) => {
812                        Some(H3Client::new(h3_connector, config.pool_idle_timeout))
813                    }
814                    None => None,
815                },
816//                hyper: builder.build(connector),
817                hyper: builder.build(connector_builder.build(config.connector_layers)),
818                headers: config.headers,
819                redirect_policy: config.redirect_policy,
820                referer: config.referer,
821                read_timeout: config.read_timeout,
822                request_timeout: config.timeout,
823                proxies,
824                proxies_maybe_http_auth,
825                https_only: config.https_only,
826            }),
827        })
828    }
829
830    // Higher-level options
831
832    /// Sets the `User-Agent` header to be used by this client.
833    ///
834    /// # Example
835    ///
836    /// ```rust
837    /// # async fn doc() -> Result<(), reqwest::Error> {
838    /// // Name your user agent after your app?
839    /// static APP_USER_AGENT: &str = concat!(
840    ///     env!("CARGO_PKG_NAME"),
841    ///     "/",
842    ///     env!("CARGO_PKG_VERSION"),
843    /// );
844    ///
845    /// let client = reqwest::Client::builder()
846    ///     .user_agent(APP_USER_AGENT)
847    ///     .build()?;
848    /// let res = client.get("https://www.rust-lang.org").send().await?;
849    /// # Ok(())
850    /// # }
851    /// ```
852    pub fn user_agent<V>(mut self, value: V) -> ClientBuilder
853    where
854        V: TryInto<HeaderValue>,
855        V::Error: Into<http::Error>,
856    {
857        match value.try_into() {
858            Ok(value) => {
859                self.config.headers.insert(USER_AGENT, value);
860            }
861            Err(e) => {
862                self.config.error = Some(crate::error::builder(e.into()));
863            }
864        };
865        self
866    }
867    /// Sets the default headers for every request.
868    ///
869    /// # Example
870    ///
871    /// ```rust
872    /// use reqwest::header;
873    /// # async fn doc() -> Result<(), reqwest::Error> {
874    /// let mut headers = header::HeaderMap::new();
875    /// headers.insert("X-MY-HEADER", header::HeaderValue::from_static("value"));
876    ///
877    /// // Consider marking security-sensitive headers with `set_sensitive`.
878    /// let mut auth_value = header::HeaderValue::from_static("secret");
879    /// auth_value.set_sensitive(true);
880    /// headers.insert(header::AUTHORIZATION, auth_value);
881    ///
882    /// // get a client builder
883    /// let client = reqwest::Client::builder()
884    ///     .default_headers(headers)
885    ///     .build()?;
886    /// let res = client.get("https://www.rust-lang.org").send().await?;
887    /// # Ok(())
888    /// # }
889    /// ```
890    pub fn default_headers(mut self, headers: HeaderMap) -> ClientBuilder {
891        for (key, value) in headers.iter() {
892            self.config.headers.insert(key, value.clone());
893        }
894        self
895    }
896
897    /// Enable a persistent cookie store for the client.
898    ///
899    /// Cookies received in responses will be preserved and included in
900    /// additional requests.
901    ///
902    /// By default, no cookie store is used. Enabling the cookie store
903    /// with `cookie_store(true)` will set the store to a default implementation.
904    /// It is **not** necessary to call [cookie_store(true)](crate::ClientBuilder::cookie_store) if [cookie_provider(my_cookie_store)](crate::ClientBuilder::cookie_provider)
905    /// is used; calling [cookie_store(true)](crate::ClientBuilder::cookie_store) _after_ [cookie_provider(my_cookie_store)](crate::ClientBuilder::cookie_provider) will result
906    /// in the provided `my_cookie_store` being **overridden** with a default implementation.
907    ///
908    /// # Optional
909    ///
910    /// This requires the optional `cookies` feature to be enabled.
911    #[cfg(feature = "cookies")]
912    #[cfg_attr(docsrs, doc(cfg(feature = "cookies")))]
913    pub fn cookie_store(mut self, enable: bool) -> ClientBuilder {
914        if enable {
915            self.cookie_provider(Arc::new(cookie::Jar::default()))
916        } else {
917            self.config.cookie_store = None;
918            self
919        }
920    }
921
922    /// Set the persistent cookie store for the client.
923    ///
924    /// Cookies received in responses will be passed to this store, and
925    /// additional requests will query this store for cookies.
926    ///
927    /// By default, no cookie store is used. It is **not** necessary to also call
928    /// [cookie_store(true)](crate::ClientBuilder::cookie_store) if [cookie_provider(my_cookie_store)](crate::ClientBuilder::cookie_provider) is used; calling
929    /// [cookie_store(true)](crate::ClientBuilder::cookie_store) _after_ [cookie_provider(my_cookie_store)](crate::ClientBuilder::cookie_provider) will result
930    /// in the provided `my_cookie_store` being **overridden** with a default implementation.
931    ///
932    /// # Optional
933    ///
934    /// This requires the optional `cookies` feature to be enabled.
935    #[cfg(feature = "cookies")]
936    #[cfg_attr(docsrs, doc(cfg(feature = "cookies")))]
937    pub fn cookie_provider<C: cookie::CookieStore + 'static>(
938        mut self,
939        cookie_store: Arc<C>,
940    ) -> ClientBuilder {
941        self.config.cookie_store = Some(cookie_store as _);
942        self
943    }
944
945    /// Enable auto gzip decompression by checking the `Content-Encoding` response header.
946    ///
947    /// If auto gzip decompression is turned on:
948    ///
949    /// - When sending a request and if the request's headers do not already contain
950    ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `gzip`.
951    ///   The request body is **not** automatically compressed.
952    /// - When receiving a response, if its headers contain a `Content-Encoding` value of
953    ///   `gzip`, both `Content-Encoding` and `Content-Length` are removed from the
954    ///   headers' set. The response body is automatically decompressed.
955    ///
956    /// If the `gzip` feature is turned on, the default option is enabled.
957    ///
958    /// # Optional
959    ///
960    /// This requires the optional `gzip` feature to be enabled
961    #[cfg(feature = "gzip")]
962    #[cfg_attr(docsrs, doc(cfg(feature = "gzip")))]
963    pub fn gzip(mut self, enable: bool) -> ClientBuilder {
964        self.config.accepts.gzip = enable;
965        self
966    }
967
968    /// Enable auto brotli decompression by checking the `Content-Encoding` response header.
969    ///
970    /// If auto brotli decompression is turned on:
971    ///
972    /// - When sending a request and if the request's headers do not already contain
973    ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `br`.
974    ///   The request body is **not** automatically compressed.
975    /// - When receiving a response, if its headers contain a `Content-Encoding` value of
976    ///   `br`, both `Content-Encoding` and `Content-Length` are removed from the
977    ///   headers' set. The response body is automatically decompressed.
978    ///
979    /// If the `brotli` feature is turned on, the default option is enabled.
980    ///
981    /// # Optional
982    ///
983    /// This requires the optional `brotli` feature to be enabled
984    #[cfg(feature = "brotli")]
985    #[cfg_attr(docsrs, doc(cfg(feature = "brotli")))]
986    pub fn brotli(mut self, enable: bool) -> ClientBuilder {
987        self.config.accepts.brotli = enable;
988        self
989    }
990
991    /// Enable auto zstd decompression by checking the `Content-Encoding` response header.
992    ///
993    /// If auto zstd decompression is turned on:
994    ///
995    /// - When sending a request and if the request's headers do not already contain
996    ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `zstd`.
997    ///   The request body is **not** automatically compressed.
998    /// - When receiving a response, if its headers contain a `Content-Encoding` value of
999    ///   `zstd`, both `Content-Encoding` and `Content-Length` are removed from the
1000    ///   headers' set. The response body is automatically decompressed.
1001    ///
1002    /// If the `zstd` feature is turned on, the default option is enabled.
1003    ///
1004    /// # Optional
1005    ///
1006    /// This requires the optional `zstd` feature to be enabled
1007    #[cfg(feature = "zstd")]
1008    #[cfg_attr(docsrs, doc(cfg(feature = "zstd")))]
1009    pub fn zstd(mut self, enable: bool) -> ClientBuilder {
1010        self.config.accepts.zstd = enable;
1011        self
1012    }
1013
1014    /// Enable auto deflate decompression by checking the `Content-Encoding` response header.
1015    ///
1016    /// If auto deflate decompression is turned on:
1017    ///
1018    /// - When sending a request and if the request's headers do not already contain
1019    ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `deflate`.
1020    ///   The request body is **not** automatically compressed.
1021    /// - When receiving a response, if it's headers contain a `Content-Encoding` value that
1022    ///   equals to `deflate`, both values `Content-Encoding` and `Content-Length` are removed from the
1023    ///   headers' set. The response body is automatically decompressed.
1024    ///
1025    /// If the `deflate` feature is turned on, the default option is enabled.
1026    ///
1027    /// # Optional
1028    ///
1029    /// This requires the optional `deflate` feature to be enabled
1030    #[cfg(feature = "deflate")]
1031    #[cfg_attr(docsrs, doc(cfg(feature = "deflate")))]
1032    pub fn deflate(mut self, enable: bool) -> ClientBuilder {
1033        self.config.accepts.deflate = enable;
1034        self
1035    }
1036
1037    /// Disable auto response body gzip decompression.
1038    ///
1039    /// This method exists even if the optional `gzip` feature is not enabled.
1040    /// This can be used to ensure a `Client` doesn't use gzip decompression
1041    /// even if another dependency were to enable the optional `gzip` feature.
1042    pub fn no_gzip(self) -> ClientBuilder {
1043        #[cfg(feature = "gzip")]
1044        {
1045            self.gzip(false)
1046        }
1047
1048        #[cfg(not(feature = "gzip"))]
1049        {
1050            self
1051        }
1052    }
1053
1054    /// Disable auto response body brotli decompression.
1055    ///
1056    /// This method exists even if the optional `brotli` feature is not enabled.
1057    /// This can be used to ensure a `Client` doesn't use brotli decompression
1058    /// even if another dependency were to enable the optional `brotli` feature.
1059    pub fn no_brotli(self) -> ClientBuilder {
1060        #[cfg(feature = "brotli")]
1061        {
1062            self.brotli(false)
1063        }
1064
1065        #[cfg(not(feature = "brotli"))]
1066        {
1067            self
1068        }
1069    }
1070
1071    /// Disable auto response body zstd decompression.
1072    ///
1073    /// This method exists even if the optional `zstd` feature is not enabled.
1074    /// This can be used to ensure a `Client` doesn't use zstd decompression
1075    /// even if another dependency were to enable the optional `zstd` feature.
1076    pub fn no_zstd(self) -> ClientBuilder {
1077        #[cfg(feature = "zstd")]
1078        {
1079            self.zstd(false)
1080        }
1081
1082        #[cfg(not(feature = "zstd"))]
1083        {
1084            self
1085        }
1086    }
1087
1088    /// Disable auto response body deflate decompression.
1089    ///
1090    /// This method exists even if the optional `deflate` feature is not enabled.
1091    /// This can be used to ensure a `Client` doesn't use deflate decompression
1092    /// even if another dependency were to enable the optional `deflate` feature.
1093    pub fn no_deflate(self) -> ClientBuilder {
1094        #[cfg(feature = "deflate")]
1095        {
1096            self.deflate(false)
1097        }
1098
1099        #[cfg(not(feature = "deflate"))]
1100        {
1101            self
1102        }
1103    }
1104
1105    // Redirect options
1106
1107    /// Set a `RedirectPolicy` for this client.
1108    ///
1109    /// Default will follow redirects up to a maximum of 10.
1110    pub fn redirect(mut self, policy: redirect::Policy) -> ClientBuilder {
1111        self.config.redirect_policy = policy;
1112        self
1113    }
1114
1115    /// Enable or disable automatic setting of the `Referer` header.
1116    ///
1117    /// Default is `true`.
1118    pub fn referer(mut self, enable: bool) -> ClientBuilder {
1119        self.config.referer = enable;
1120        self
1121    }
1122
1123    // Proxy options
1124
1125    /// Add a `Proxy` to the list of proxies the `Client` will use.
1126    ///
1127    /// # Note
1128    ///
1129    /// Adding a proxy will disable the automatic usage of the "system" proxy.
1130    pub fn proxy(mut self, proxy: Proxy) -> ClientBuilder {
1131        self.config.proxies.push(proxy);
1132        self.config.auto_sys_proxy = false;
1133        self
1134    }
1135
1136    /// Clear all `Proxies`, so `Client` will use no proxy anymore.
1137    ///
1138    /// # Note
1139    /// To add a proxy exclusion list, use [crate::proxy::Proxy::no_proxy()]
1140    /// on all desired proxies instead.
1141    ///
1142    /// This also disables the automatic usage of the "system" proxy.
1143    pub fn no_proxy(mut self) -> ClientBuilder {
1144        self.config.proxies.clear();
1145        self.config.auto_sys_proxy = false;
1146        self
1147    }
1148
1149    // Timeout options
1150
1151    /// Enables a total request timeout.
1152    ///
1153    /// The timeout is applied from when the request starts connecting until the
1154    /// response body has finished. Also considered a total deadline.
1155    ///
1156    /// Default is no timeout.
1157    pub fn timeout(mut self, timeout: Duration) -> ClientBuilder {
1158        self.config.timeout = Some(timeout);
1159        self
1160    }
1161
1162    /// Enables a read timeout.
1163    ///
1164    /// The timeout applies to each read operation, and resets after a
1165    /// successful read. This is more appropriate for detecting stalled
1166    /// connections when the size isn't known beforehand.
1167    ///
1168    /// Default is no timeout.
1169    pub fn read_timeout(mut self, timeout: Duration) -> ClientBuilder {
1170        self.config.read_timeout = Some(timeout);
1171        self
1172    }
1173
1174    /// Set a timeout for only the connect phase of a `Client`.
1175    ///
1176    /// Default is `None`.
1177    ///
1178    /// # Note
1179    ///
1180    /// This **requires** the futures be executed in a tokio runtime with
1181    /// a tokio timer enabled.
1182    pub fn connect_timeout(mut self, timeout: Duration) -> ClientBuilder {
1183        self.config.connect_timeout = Some(timeout);
1184        self
1185    }
1186
1187    /// Set whether connections should emit verbose logs.
1188    ///
1189    /// Enabling this option will emit [log][] messages at the `TRACE` level
1190    /// for read and write operations on connections.
1191    ///
1192    /// [log]: https://crates.io/crates/log
1193    pub fn connection_verbose(mut self, verbose: bool) -> ClientBuilder {
1194        self.config.connection_verbose = verbose;
1195        self
1196    }
1197
1198    // HTTP options
1199
1200    /// Set an optional timeout for idle sockets being kept-alive.
1201    ///
1202    /// Pass `None` to disable timeout.
1203    ///
1204    /// Default is 90 seconds.
1205    pub fn pool_idle_timeout<D>(mut self, val: D) -> ClientBuilder
1206    where
1207        D: Into<Option<Duration>>,
1208    {
1209        self.config.pool_idle_timeout = val.into();
1210        self
1211    }
1212
1213    /// Sets the maximum idle connection per host allowed in the pool.
1214    pub fn pool_max_idle_per_host(mut self, max: usize) -> ClientBuilder {
1215        self.config.pool_max_idle_per_host = max;
1216        self
1217    }
1218
1219    /// Send headers as title case instead of lowercase.
1220    pub fn http1_title_case_headers(mut self) -> ClientBuilder {
1221        self.config.http1_title_case_headers = true;
1222        self
1223    }
1224
1225    /// Set whether HTTP/1 connections will accept obsolete line folding for
1226    /// header values.
1227    ///
1228    /// Newline codepoints (`\r` and `\n`) will be transformed to spaces when
1229    /// parsing.
1230    pub fn http1_allow_obsolete_multiline_headers_in_responses(
1231        mut self,
1232        value: bool,
1233    ) -> ClientBuilder {
1234        self.config
1235            .http1_allow_obsolete_multiline_headers_in_responses = value;
1236        self
1237    }
1238
1239    /// Sets whether invalid header lines should be silently ignored in HTTP/1 responses.
1240    pub fn http1_ignore_invalid_headers_in_responses(mut self, value: bool) -> ClientBuilder {
1241        self.config.http1_ignore_invalid_headers_in_responses = value;
1242        self
1243    }
1244
1245    /// Set whether HTTP/1 connections will accept spaces between header
1246    /// names and the colon that follow them in responses.
1247    ///
1248    /// Newline codepoints (`\r` and `\n`) will be transformed to spaces when
1249    /// parsing.
1250    pub fn http1_allow_spaces_after_header_name_in_responses(
1251        mut self,
1252        value: bool,
1253    ) -> ClientBuilder {
1254        self.config
1255            .http1_allow_spaces_after_header_name_in_responses = value;
1256        self
1257    }
1258
1259    /// Only use HTTP/1.
1260    pub fn http1_only(mut self) -> ClientBuilder {
1261        self.config.http_version_pref = HttpVersionPref::Http1;
1262        self
1263    }
1264
1265    /// Allow HTTP/0.9 responses
1266    pub fn http09_responses(mut self) -> ClientBuilder {
1267        self.config.http09_responses = true;
1268        self
1269    }
1270
1271    /// Only use HTTP/2.
1272    #[cfg(feature = "http2")]
1273    #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
1274    pub fn http2_prior_knowledge(mut self) -> ClientBuilder {
1275        self.config.http_version_pref = HttpVersionPref::Http2;
1276        self
1277    }
1278
1279    /// Only use HTTP/3.
1280    #[cfg(feature = "http3")]
1281    #[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", feature = "http3",))))]
1282    pub fn http3_prior_knowledge(mut self) -> ClientBuilder {
1283        self.config.http_version_pref = HttpVersionPref::Http3;
1284        self
1285    }
1286
1287    /// Sets the `SETTINGS_INITIAL_WINDOW_SIZE` option for HTTP2 stream-level flow control.
1288    ///
1289    /// Default is currently 65,535 but may change internally to optimize for common uses.
1290    #[cfg(feature = "http2")]
1291    #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
1292    pub fn http2_initial_stream_window_size(mut self, sz: impl Into<Option<u32>>) -> ClientBuilder {
1293        self.config.http2_initial_stream_window_size = sz.into();
1294        self
1295    }
1296
1297    /// Sets the max connection-level flow control for HTTP2
1298    ///
1299    /// Default is currently 65,535 but may change internally to optimize for common uses.
1300    #[cfg(feature = "http2")]
1301    #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
1302    pub fn http2_initial_connection_window_size(
1303        mut self,
1304        sz: impl Into<Option<u32>>,
1305    ) -> ClientBuilder {
1306        self.config.http2_initial_connection_window_size = sz.into();
1307        self
1308    }
1309
1310    /// Sets whether to use an adaptive flow control.
1311    ///
1312    /// Enabling this will override the limits set in `http2_initial_stream_window_size` and
1313    /// `http2_initial_connection_window_size`.
1314    #[cfg(feature = "http2")]
1315    #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
1316    pub fn http2_adaptive_window(mut self, enabled: bool) -> ClientBuilder {
1317        self.config.http2_adaptive_window = enabled;
1318        self
1319    }
1320
1321    /// Sets the maximum frame size to use for HTTP2.
1322    ///
1323    /// Default is currently 16,384 but may change internally to optimize for common uses.
1324    #[cfg(feature = "http2")]
1325    #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
1326    pub fn http2_max_frame_size(mut self, sz: impl Into<Option<u32>>) -> ClientBuilder {
1327        self.config.http2_max_frame_size = sz.into();
1328        self
1329    }
1330
1331    /// Sets the maximum size of received header frames for HTTP2.
1332    ///
1333    /// Default is currently 16KB, but can change.
1334    #[cfg(feature = "http2")]
1335    #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
1336    pub fn http2_max_header_list_size(mut self, max_header_size_bytes: u32) -> ClientBuilder {
1337        self.config.http2_max_header_list_size = Some(max_header_size_bytes);
1338        self
1339    }
1340
1341    /// Sets an interval for HTTP2 Ping frames should be sent to keep a connection alive.
1342    ///
1343    /// Pass `None` to disable HTTP2 keep-alive.
1344    /// Default is currently disabled.
1345    #[cfg(feature = "http2")]
1346    #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
1347    pub fn http2_keep_alive_interval(
1348        mut self,
1349        interval: impl Into<Option<Duration>>,
1350    ) -> ClientBuilder {
1351        self.config.http2_keep_alive_interval = interval.into();
1352        self
1353    }
1354
1355    /// Sets a timeout for receiving an acknowledgement of the keep-alive ping.
1356    ///
1357    /// If the ping is not acknowledged within the timeout, the connection will be closed.
1358    /// Does nothing if `http2_keep_alive_interval` is disabled.
1359    /// Default is currently disabled.
1360    #[cfg(feature = "http2")]
1361    #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
1362    pub fn http2_keep_alive_timeout(mut self, timeout: Duration) -> ClientBuilder {
1363        self.config.http2_keep_alive_timeout = Some(timeout);
1364        self
1365    }
1366
1367    /// Sets whether HTTP2 keep-alive should apply while the connection is idle.
1368    ///
1369    /// If disabled, keep-alive pings are only sent while there are open request/responses streams.
1370    /// If enabled, pings are also sent when no streams are active.
1371    /// Does nothing if `http2_keep_alive_interval` is disabled.
1372    /// Default is `false`.
1373    #[cfg(feature = "http2")]
1374    #[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
1375    pub fn http2_keep_alive_while_idle(mut self, enabled: bool) -> ClientBuilder {
1376        self.config.http2_keep_alive_while_idle = enabled;
1377        self
1378    }
1379
1380    // TCP options
1381
1382    /// Set whether sockets have `TCP_NODELAY` enabled.
1383    ///
1384    /// Default is `true`.
1385    pub fn tcp_nodelay(mut self, enabled: bool) -> ClientBuilder {
1386        self.config.nodelay = enabled;
1387        self
1388    }
1389
1390    /// Bind to a local IP Address.
1391    ///
1392    /// # Example
1393    ///
1394    /// ```
1395    /// # #[cfg(all(feature = "__rustls", not(feature = "__rustls-ring")))]
1396    /// # let _ = rustls::crypto::ring::default_provider().install_default();
1397    /// use std::net::IpAddr;
1398    /// let local_addr = IpAddr::from([12, 4, 1, 8]);
1399    /// let client = reqwest::Client::builder()
1400    ///     .local_address(local_addr)
1401    ///     .build().unwrap();
1402    /// ```
1403    pub fn local_address<T>(mut self, addr: T) -> ClientBuilder
1404    where
1405        T: Into<Option<IpAddr>>,
1406    {
1407        self.config.local_address = addr.into();
1408        self
1409    }
1410
1411    /// Bind to an interface by `SO_BINDTODEVICE`.
1412    ///
1413    /// # Example
1414    ///
1415    /// ```
1416    /// # #[cfg(all(feature = "__rustls", not(feature = "__rustls-ring")))]
1417    /// # let _ = rustls::crypto::ring::default_provider().install_default();
1418    /// let interface = "lo";
1419    /// let client = reqwest::Client::builder()
1420    ///     .interface(interface)
1421    ///     .build().unwrap();
1422    /// ```
1423    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
1424    pub fn interface(mut self, interface: &str) -> ClientBuilder {
1425        self.config.interface = Some(interface.to_string());
1426        self
1427    }
1428
1429    /// Set that all sockets have `SO_KEEPALIVE` set with the supplied duration.
1430    ///
1431    /// If `None`, the option will not be set.
1432    pub fn tcp_keepalive<D>(mut self, val: D) -> ClientBuilder
1433    where
1434        D: Into<Option<Duration>>,
1435    {
1436        self.config.tcp_keepalive = val.into();
1437        self
1438    }
1439
1440    // TLS options
1441
1442    /// Add a custom root certificate.
1443    ///
1444    /// This can be used to connect to a server that has a self-signed
1445    /// certificate for example.
1446    ///
1447    /// # Optional
1448    ///
1449    /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
1450    /// feature to be enabled.
1451    #[cfg(feature = "__tls")]
1452    #[cfg_attr(
1453        docsrs,
1454        doc(cfg(any(
1455            feature = "default-tls",
1456            feature = "native-tls",
1457            feature = "rustls-tls"
1458        )))
1459    )]
1460    pub fn add_root_certificate(mut self, cert: Certificate) -> ClientBuilder {
1461        self.config.root_certs.push(cert);
1462        self
1463    }
1464
1465    /// Add a certificate revocation list.
1466    ///
1467    ///
1468    /// # Optional
1469    ///
1470    /// This requires the `rustls-tls(-...)` Cargo feature enabled.
1471    #[cfg(feature = "__rustls")]
1472    #[cfg_attr(docsrs, doc(cfg(feature = "rustls-tls")))]
1473    pub fn add_crl(mut self, crl: CertificateRevocationList) -> ClientBuilder {
1474        self.config.crls.push(crl);
1475        self
1476    }
1477
1478    /// Add multiple certificate revocation lists.
1479    ///
1480    ///
1481    /// # Optional
1482    ///
1483    /// This requires the `rustls-tls(-...)` Cargo feature enabled.
1484    #[cfg(feature = "__rustls")]
1485    #[cfg_attr(docsrs, doc(cfg(feature = "rustls-tls")))]
1486    pub fn add_crls(
1487        mut self,
1488        crls: impl IntoIterator<Item = CertificateRevocationList>,
1489    ) -> ClientBuilder {
1490        self.config.crls.extend(crls);
1491        self
1492    }
1493
1494    /// Controls the use of built-in/preloaded certificates during certificate validation.
1495    ///
1496    /// Defaults to `true` -- built-in system certs will be used.
1497    ///
1498    /// # Bulk Option
1499    ///
1500    /// If this value is `true`, _all_ enabled system certs configured with Cargo
1501    /// features will be loaded.
1502    ///
1503    /// You can set this to `false`, and enable only a specific source with
1504    /// individual methods. Do that will prevent other sources from being loaded
1505    /// even if their feature Cargo feature is enabled.
1506    ///
1507    /// # Optional
1508    ///
1509    /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
1510    /// feature to be enabled.
1511    #[cfg(feature = "__tls")]
1512    #[cfg_attr(
1513        docsrs,
1514        doc(cfg(any(
1515            feature = "default-tls",
1516            feature = "native-tls",
1517            feature = "rustls-tls"
1518        )))
1519    )]
1520    pub fn tls_built_in_root_certs(mut self, tls_built_in_root_certs: bool) -> ClientBuilder {
1521        self.config.tls_built_in_root_certs = tls_built_in_root_certs;
1522
1523        #[cfg(feature = "rustls-tls-webpki-roots-no-provider")]
1524        {
1525            self.config.tls_built_in_certs_webpki = tls_built_in_root_certs;
1526        }
1527
1528        #[cfg(feature = "rustls-tls-native-roots-no-provider")]
1529        {
1530            self.config.tls_built_in_certs_native = tls_built_in_root_certs;
1531        }
1532
1533        self
1534    }
1535
1536    /// Sets whether to load webpki root certs with rustls.
1537    ///
1538    /// If the feature is enabled, this value is `true` by default.
1539    #[cfg(feature = "rustls-tls-webpki-roots-no-provider")]
1540    #[cfg_attr(docsrs, doc(cfg(feature = "rustls-tls-webpki-roots-no-provider")))]
1541    pub fn tls_built_in_webpki_certs(mut self, enabled: bool) -> ClientBuilder {
1542        self.config.tls_built_in_certs_webpki = enabled;
1543        self
1544    }
1545
1546    /// Sets whether to load native root certs with rustls.
1547    ///
1548    /// If the feature is enabled, this value is `true` by default.
1549    #[cfg(feature = "rustls-tls-native-roots-no-provider")]
1550    #[cfg_attr(docsrs, doc(cfg(feature = "rustls-tls-native-roots-no-provider")))]
1551    pub fn tls_built_in_native_certs(mut self, enabled: bool) -> ClientBuilder {
1552        self.config.tls_built_in_certs_native = enabled;
1553        self
1554    }
1555
1556    /// Sets the identity to be used for client certificate authentication.
1557    ///
1558    /// # Optional
1559    ///
1560    /// This requires the optional `native-tls` or `rustls-tls(-...)` feature to be
1561    /// enabled.
1562    #[cfg(any(feature = "native-tls", feature = "__rustls"))]
1563    #[cfg_attr(docsrs, doc(cfg(any(feature = "native-tls", feature = "rustls-tls"))))]
1564    pub fn identity(mut self, identity: Identity) -> ClientBuilder {
1565        self.config.identity = Some(identity);
1566        self
1567    }
1568
1569    /// Controls the use of hostname verification.
1570    ///
1571    /// Defaults to `false`.
1572    ///
1573    /// # Warning
1574    ///
1575    /// You should think very carefully before you use this method. If
1576    /// hostname verification is not used, any valid certificate for any
1577    /// site will be trusted for use from any other. This introduces a
1578    /// significant vulnerability to man-in-the-middle attacks.
1579    ///
1580    /// # Optional
1581    ///
1582    /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
1583    /// feature to be enabled.
1584    #[cfg(feature = "__tls")]
1585    #[cfg_attr(
1586        docsrs,
1587        doc(cfg(any(
1588            feature = "default-tls",
1589            feature = "native-tls",
1590            feature = "rustls-tls"
1591        )))
1592    )]
1593    pub fn danger_accept_invalid_hostnames(
1594        mut self,
1595        accept_invalid_hostname: bool,
1596    ) -> ClientBuilder {
1597        self.config.hostname_verification = !accept_invalid_hostname;
1598        self
1599    }
1600
1601    /// Controls the use of certificate validation.
1602    ///
1603    /// Defaults to `false`.
1604    ///
1605    /// # Warning
1606    ///
1607    /// You should think very carefully before using this method. If
1608    /// invalid certificates are trusted, *any* certificate for *any* site
1609    /// will be trusted for use. This includes expired certificates. This
1610    /// introduces significant vulnerabilities, and should only be used
1611    /// as a last resort.
1612    ///
1613    /// # Optional
1614    ///
1615    /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
1616    /// feature to be enabled.
1617    #[cfg(feature = "__tls")]
1618    #[cfg_attr(
1619        docsrs,
1620        doc(cfg(any(
1621            feature = "default-tls",
1622            feature = "native-tls",
1623            feature = "rustls-tls"
1624        )))
1625    )]
1626    pub fn danger_accept_invalid_certs(mut self, accept_invalid_certs: bool) -> ClientBuilder {
1627        self.config.certs_verification = !accept_invalid_certs;
1628        self
1629    }
1630
1631    /// Controls the use of TLS server name indication.
1632    ///
1633    /// Defaults to `true`.
1634    ///
1635    /// # Optional
1636    ///
1637    /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
1638    /// feature to be enabled.
1639    #[cfg(feature = "__tls")]
1640    #[cfg_attr(
1641        docsrs,
1642        doc(cfg(any(
1643            feature = "default-tls",
1644            feature = "native-tls",
1645            feature = "rustls-tls"
1646        )))
1647    )]
1648    pub fn tls_sni(mut self, tls_sni: bool) -> ClientBuilder {
1649        self.config.tls_sni = tls_sni;
1650        self
1651    }
1652
1653    /// Set the minimum required TLS version for connections.
1654    ///
1655    /// By default, the TLS backend's own default is used.
1656    ///
1657    /// # Errors
1658    ///
1659    /// A value of `tls::Version::TLS_1_3` will cause an error with the
1660    /// `native-tls`/`default-tls` backend. This does not mean the version
1661    /// isn't supported, just that it can't be set as a minimum due to
1662    /// technical limitations.
1663    ///
1664    /// # Optional
1665    ///
1666    /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
1667    /// feature to be enabled.
1668    #[cfg(feature = "__tls")]
1669    #[cfg_attr(
1670        docsrs,
1671        doc(cfg(any(
1672            feature = "default-tls",
1673            feature = "native-tls",
1674            feature = "rustls-tls"
1675        )))
1676    )]
1677    pub fn min_tls_version(mut self, version: tls::Version) -> ClientBuilder {
1678        self.config.min_tls_version = Some(version);
1679        self
1680    }
1681
1682    /// Set the maximum allowed TLS version for connections.
1683    ///
1684    /// By default, there's no maximum.
1685    ///
1686    /// # Errors
1687    ///
1688    /// A value of `tls::Version::TLS_1_3` will cause an error with the
1689    /// `native-tls`/`default-tls` backend. This does not mean the version
1690    /// isn't supported, just that it can't be set as a maximum due to
1691    /// technical limitations.
1692    ///
1693    /// Cannot set a maximum outside the protocol versions supported by
1694    /// `rustls` with the `rustls-tls` backend.
1695    ///
1696    /// # Optional
1697    ///
1698    /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
1699    /// feature to be enabled.
1700    #[cfg(feature = "__tls")]
1701    #[cfg_attr(
1702        docsrs,
1703        doc(cfg(any(
1704            feature = "default-tls",
1705            feature = "native-tls",
1706            feature = "rustls-tls"
1707        )))
1708    )]
1709    pub fn max_tls_version(mut self, version: tls::Version) -> ClientBuilder {
1710        self.config.max_tls_version = Some(version);
1711        self
1712    }
1713
1714    /// Force using the native TLS backend.
1715    ///
1716    /// Since multiple TLS backends can be optionally enabled, this option will
1717    /// force the `native-tls` backend to be used for this `Client`.
1718    ///
1719    /// # Optional
1720    ///
1721    /// This requires the optional `native-tls` feature to be enabled.
1722    #[cfg(feature = "native-tls")]
1723    #[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))]
1724    pub fn use_native_tls(mut self) -> ClientBuilder {
1725        self.config.tls = TlsBackend::Default;
1726        self
1727    }
1728
1729    /// Force using the Rustls TLS backend.
1730    ///
1731    /// Since multiple TLS backends can be optionally enabled, this option will
1732    /// force the `rustls` backend to be used for this `Client`.
1733    ///
1734    /// # Optional
1735    ///
1736    /// This requires the optional `rustls-tls(-...)` feature to be enabled.
1737    #[cfg(feature = "__rustls")]
1738    #[cfg_attr(docsrs, doc(cfg(feature = "rustls-tls")))]
1739    pub fn use_rustls_tls(mut self) -> ClientBuilder {
1740        self.config.tls = TlsBackend::Rustls;
1741        self
1742    }
1743
1744    /// Use a preconfigured TLS backend.
1745    ///
1746    /// If the passed `Any` argument is not a TLS backend that reqwest
1747    /// understands, the `ClientBuilder` will error when calling `build`.
1748    ///
1749    /// # Advanced
1750    ///
1751    /// This is an advanced option, and can be somewhat brittle. Usage requires
1752    /// keeping the preconfigured TLS argument version in sync with reqwest,
1753    /// since version mismatches will result in an "unknown" TLS backend.
1754    ///
1755    /// If possible, it's preferable to use the methods on `ClientBuilder`
1756    /// to configure reqwest's TLS.
1757    ///
1758    /// # Optional
1759    ///
1760    /// This requires one of the optional features `native-tls` or
1761    /// `rustls-tls(-...)` to be enabled.
1762    #[cfg(any(feature = "native-tls", feature = "__rustls",))]
1763    #[cfg_attr(docsrs, doc(cfg(any(feature = "native-tls", feature = "rustls-tls"))))]
1764    pub fn use_preconfigured_tls(mut self, tls: impl Any) -> ClientBuilder {
1765        let mut tls = Some(tls);
1766        #[cfg(feature = "native-tls")]
1767        {
1768            if let Some(conn) = (&mut tls as &mut dyn Any).downcast_mut::<Option<TlsConnector>>() {
1769                let tls = conn.take().expect("is definitely Some");
1770                let tls = crate::tls::TlsBackend::BuiltNativeTls(tls);
1771                self.config.tls = tls;
1772                return self;
1773            }
1774        }
1775        #[cfg(feature = "__rustls")]
1776        {
1777            if let Some(conn) =
1778                (&mut tls as &mut dyn Any).downcast_mut::<Option<rustls::ClientConfig>>()
1779            {
1780                let tls = conn.take().expect("is definitely Some");
1781                let tls = crate::tls::TlsBackend::BuiltRustls(tls);
1782                self.config.tls = tls;
1783                return self;
1784            }
1785        }
1786
1787        // Otherwise, we don't recognize the TLS backend!
1788        self.config.tls = crate::tls::TlsBackend::UnknownPreconfigured;
1789        self
1790    }
1791
1792    /// Add TLS information as `TlsInfo` extension to responses.
1793    ///
1794    /// # Optional
1795    ///
1796    /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
1797    /// feature to be enabled.
1798    #[cfg(feature = "__tls")]
1799    #[cfg_attr(
1800        docsrs,
1801        doc(cfg(any(
1802            feature = "default-tls",
1803            feature = "native-tls",
1804            feature = "rustls-tls"
1805        )))
1806    )]
1807    pub fn tls_info(mut self, tls_info: bool) -> ClientBuilder {
1808        self.config.tls_info = tls_info;
1809        self
1810    }
1811
1812    /// Restrict the Client to be used with HTTPS only requests.
1813    ///
1814    /// Defaults to false.
1815    pub fn https_only(mut self, enabled: bool) -> ClientBuilder {
1816        self.config.https_only = enabled;
1817        self
1818    }
1819
1820    #[doc(hidden)]
1821    #[cfg(feature = "hickory-dns")]
1822    #[cfg_attr(docsrs, doc(cfg(feature = "hickory-dns")))]
1823    #[deprecated(note = "use `hickory_dns` instead")]
1824    pub fn trust_dns(mut self, enable: bool) -> ClientBuilder {
1825        self.config.hickory_dns = enable;
1826        self
1827    }
1828
1829    /// Enables the [hickory-dns](hickory_resolver) async resolver instead of a default threadpool
1830    /// using `getaddrinfo`.
1831    ///
1832    /// If the `hickory-dns` feature is turned on, the default option is enabled.
1833    ///
1834    /// # Optional
1835    ///
1836    /// This requires the optional `hickory-dns` feature to be enabled
1837    ///
1838    /// # Warning
1839    ///
1840    /// The hickory resolver does not work exactly the same, or on all the platforms
1841    /// that the default resolver does
1842    #[cfg(feature = "hickory-dns")]
1843    #[cfg_attr(docsrs, doc(cfg(feature = "hickory-dns")))]
1844    pub fn hickory_dns(mut self, enable: bool) -> ClientBuilder {
1845        self.config.hickory_dns = enable;
1846        self
1847    }
1848
1849    #[doc(hidden)]
1850    #[deprecated(note = "use `no_hickory_dns` instead")]
1851    pub fn no_trust_dns(self) -> ClientBuilder {
1852        self.no_hickory_dns()
1853    }
1854
1855    /// Disables the hickory-dns async resolver.
1856    ///
1857    /// This method exists even if the optional `hickory-dns` feature is not enabled.
1858    /// This can be used to ensure a `Client` doesn't use the hickory-dns async resolver
1859    /// even if another dependency were to enable the optional `hickory-dns` feature.
1860    pub fn no_hickory_dns(self) -> ClientBuilder {
1861        #[cfg(feature = "hickory-dns")]
1862        {
1863            self.hickory_dns(false)
1864        }
1865
1866        #[cfg(not(feature = "hickory-dns"))]
1867        {
1868            self
1869        }
1870    }
1871
1872    /// Override DNS resolution for specific domains to a particular IP address.
1873    ///
1874    /// Set the port to `0` to use the conventional port for the given scheme (e.g. 80 for http).
1875    /// Ports in the URL itself will always be used instead of the port in the overridden addr.
1876    pub fn resolve(self, domain: &str, addr: SocketAddr) -> ClientBuilder {
1877        self.resolve_to_addrs(domain, &[addr])
1878    }
1879
1880    /// Override DNS resolution for specific domains to particular IP addresses.
1881    ///
1882    /// Set the port to `0` to use the conventional port for the given scheme (e.g. 80 for http).
1883    /// Ports in the URL itself will always be used instead of the port in the overridden addr.
1884    pub fn resolve_to_addrs(mut self, domain: &str, addrs: &[SocketAddr]) -> ClientBuilder {
1885        self.config
1886            .dns_overrides
1887            .insert(domain.to_ascii_lowercase(), addrs.to_vec());
1888        self
1889    }
1890
1891    /// Override the DNS resolver implementation.
1892    ///
1893    /// Pass an `Arc` wrapping a trait object implementing `Resolve`.
1894    /// Overrides for specific names passed to `resolve` and `resolve_to_addrs` will
1895    /// still be applied on top of this resolver.
1896    pub fn dns_resolver<R: Resolve + 'static>(mut self, resolver: Arc<R>) -> ClientBuilder {
1897        self.config.dns_resolver = Some(resolver as _);
1898        self
1899    }
1900
1901    /// Whether to send data on the first flight ("early data") in TLS 1.3 handshakes
1902    /// for HTTP/3 connections.
1903    ///
1904    /// The default is false.
1905    #[cfg(feature = "http3")]
1906    #[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", feature = "http3",))))]
1907    pub fn tls_early_data(mut self, enabled: bool) -> ClientBuilder {
1908        self.config.tls_enable_early_data = enabled;
1909        self
1910    }
1911
1912    /// Maximum duration of inactivity to accept before timing out the QUIC connection.
1913    ///
1914    /// Please see docs in [`TransportConfig`] in [`quinn`].
1915    ///
1916    /// [`TransportConfig`]: https://docs.rs/quinn/latest/quinn/struct.TransportConfig.html
1917    #[cfg(feature = "http3")]
1918    #[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", feature = "http3",))))]
1919    pub fn http3_max_idle_timeout(mut self, value: Duration) -> ClientBuilder {
1920        self.config.quic_max_idle_timeout = Some(value);
1921        self
1922    }
1923
1924    /// Maximum number of bytes the peer may transmit without acknowledgement on any one stream
1925    /// before becoming blocked.
1926    ///
1927    /// Please see docs in [`TransportConfig`] in [`quinn`].
1928    ///
1929    /// [`TransportConfig`]: https://docs.rs/quinn/latest/quinn/struct.TransportConfig.html
1930    ///
1931    /// # Panics
1932    ///
1933    /// Panics if the value is over 2^62.
1934    #[cfg(feature = "http3")]
1935    #[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", feature = "http3",))))]
1936    pub fn http3_stream_receive_window(mut self, value: u64) -> ClientBuilder {
1937        self.config.quic_stream_receive_window = Some(value.try_into().unwrap());
1938        self
1939    }
1940
1941    /// Maximum number of bytes the peer may transmit across all streams of a connection before
1942    /// becoming blocked.
1943    ///
1944    /// Please see docs in [`TransportConfig`] in [`quinn`].
1945    ///
1946    /// [`TransportConfig`]: https://docs.rs/quinn/latest/quinn/struct.TransportConfig.html
1947    ///
1948    /// # Panics
1949    ///
1950    /// Panics if the value is over 2^62.
1951    #[cfg(feature = "http3")]
1952    #[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", feature = "http3",))))]
1953    pub fn http3_conn_receive_window(mut self, value: u64) -> ClientBuilder {
1954        self.config.quic_receive_window = Some(value.try_into().unwrap());
1955        self
1956    }
1957
1958    /// Maximum number of bytes to transmit to a peer without acknowledgment
1959    ///
1960    /// Please see docs in [`TransportConfig`] in [`quinn`].
1961    ///
1962    /// [`TransportConfig`]: https://docs.rs/quinn/latest/quinn/struct.TransportConfig.html
1963    #[cfg(feature = "http3")]
1964    #[cfg_attr(docsrs, doc(cfg(all(feature = "unstable", feature = "http3",))))]
1965    pub fn http3_send_window(mut self, value: u64) -> ClientBuilder {
1966        self.config.quic_send_window = Some(value);
1967        self
1968    }
1969
1970    /// Adds a new Tower [`Layer`](https://docs.rs/tower/latest/tower/trait.Layer.html) to the
1971    /// base connector [`Service`](https://docs.rs/tower/latest/tower/trait.Service.html) which
1972    /// is responsible for connection establishment.
1973    ///
1974    /// Each subsequent invocation of this function will wrap previous layers.
1975    ///
1976    /// If configured, the `connect_timeout` will be the outermost layer.
1977    ///
1978    /// Example usage:
1979    /// ```
1980    /// use std::time::Duration;
1981    ///
1982    /// # #[cfg(not(feature = "rustls-tls-no-provider"))]
1983    /// let client = reqwest::Client::builder()
1984    ///                      // resolved to outermost layer, meaning while we are waiting on concurrency limit
1985    ///                      .connect_timeout(Duration::from_millis(200))
1986    ///                      // underneath the concurrency check, so only after concurrency limit lets us through
1987    ///                      .connector_layer(tower::timeout::TimeoutLayer::new(Duration::from_millis(50)))
1988    ///                      .connector_layer(tower::limit::concurrency::ConcurrencyLimitLayer::new(2))
1989    ///                      .build()
1990    ///                      .unwrap();
1991    /// ```
1992    ///
1993    pub fn connector_layer<L>(mut self, layer: L) -> ClientBuilder
1994    where
1995        L: Layer<BoxedConnectorService> + Clone + Send + Sync + 'static,
1996        L::Service:
1997            Service<Unnameable, Response = Conn, Error = BoxError> + Clone + Send + Sync + 'static,
1998        <L::Service as Service<Unnameable>>::Future: Send + 'static,
1999    {
2000        let layer = BoxCloneSyncServiceLayer::new(layer);
2001
2002        self.config.connector_layers.push(layer);
2003
2004        self
2005    }
2006}
2007
2008type HyperClient = hyper_util::client::legacy::Client<Connector, super::Body>;
2009
2010impl Default for Client {
2011    fn default() -> Self {
2012        Self::new()
2013    }
2014}
2015
2016impl Client {
2017    /// Constructs a new `Client`.
2018    ///
2019    /// # Panics
2020    ///
2021    /// This method panics if a TLS backend cannot be initialized, or the resolver
2022    /// cannot load the system configuration.
2023    ///
2024    /// Use `Client::builder()` if you wish to handle the failure as an `Error`
2025    /// instead of panicking.
2026    pub fn new() -> Client {
2027        ClientBuilder::new().build().expect("Client::new()")
2028    }
2029
2030    /// Creates a `ClientBuilder` to configure a `Client`.
2031    ///
2032    /// This is the same as `ClientBuilder::new()`.
2033    pub fn builder() -> ClientBuilder {
2034        ClientBuilder::new()
2035    }
2036
2037    /// Convenience method to make a `GET` request to a URL.
2038    ///
2039    /// # Errors
2040    ///
2041    /// This method fails whenever the supplied `Url` cannot be parsed.
2042    pub fn get<U: IntoUrl>(&self, url: U) -> RequestBuilder {
2043        self.request(Method::GET, url)
2044    }
2045
2046    /// Convenience method to make a `POST` request to a URL.
2047    ///
2048    /// # Errors
2049    ///
2050    /// This method fails whenever the supplied `Url` cannot be parsed.
2051    pub fn post<U: IntoUrl>(&self, url: U) -> RequestBuilder {
2052        self.request(Method::POST, url)
2053    }
2054
2055    /// Convenience method to make a `PUT` request to a URL.
2056    ///
2057    /// # Errors
2058    ///
2059    /// This method fails whenever the supplied `Url` cannot be parsed.
2060    pub fn put<U: IntoUrl>(&self, url: U) -> RequestBuilder {
2061        self.request(Method::PUT, url)
2062    }
2063
2064    /// Convenience method to make a `PATCH` request to a URL.
2065    ///
2066    /// # Errors
2067    ///
2068    /// This method fails whenever the supplied `Url` cannot be parsed.
2069    pub fn patch<U: IntoUrl>(&self, url: U) -> RequestBuilder {
2070        self.request(Method::PATCH, url)
2071    }
2072
2073    /// Convenience method to make a `DELETE` request to a URL.
2074    ///
2075    /// # Errors
2076    ///
2077    /// This method fails whenever the supplied `Url` cannot be parsed.
2078    pub fn delete<U: IntoUrl>(&self, url: U) -> RequestBuilder {
2079        self.request(Method::DELETE, url)
2080    }
2081
2082    /// Convenience method to make a `HEAD` request to a URL.
2083    ///
2084    /// # Errors
2085    ///
2086    /// This method fails whenever the supplied `Url` cannot be parsed.
2087    pub fn head<U: IntoUrl>(&self, url: U) -> RequestBuilder {
2088        self.request(Method::HEAD, url)
2089    }
2090
2091    /// Start building a `Request` with the `Method` and `Url`.
2092    ///
2093    /// Returns a `RequestBuilder`, which will allow setting headers and
2094    /// the request body before sending.
2095    ///
2096    /// # Errors
2097    ///
2098    /// This method fails whenever the supplied `Url` cannot be parsed.
2099    pub fn request<U: IntoUrl>(&self, method: Method, url: U) -> RequestBuilder {
2100        let req = url.into_url().map(move |url| Request::new(method, url));
2101        RequestBuilder::new(self.clone(), req)
2102    }
2103
2104    /// Executes a `Request`.
2105    ///
2106    /// A `Request` can be built manually with `Request::new()` or obtained
2107    /// from a RequestBuilder with `RequestBuilder::build()`.
2108    ///
2109    /// You should prefer to use the `RequestBuilder` and
2110    /// `RequestBuilder::send()`.
2111    ///
2112    /// # Errors
2113    ///
2114    /// This method fails if there was an error while sending request,
2115    /// redirect loop was detected or redirect limit was exhausted.
2116    pub fn execute(
2117        &self,
2118        request: Request,
2119    ) -> impl Future<Output = Result<Response, crate::Error>> {
2120        self.execute_request(request)
2121    }
2122
2123    pub(super) fn execute_request(&self, req: Request) -> Pending {
2124        let (method, url, mut headers, body, timeout, mut version) = req.pieces();
2125
2126        #[cfg(feature = "http3")]
2127        if self.inner.h3_client.is_some() {
2128            version = http::Version::HTTP_3;
2129        }
2130
2131        if url.scheme() != "http" && url.scheme() != "https" {
2132            return Pending::new_err(error::url_bad_scheme(url));
2133        }
2134
2135        // check if we're in https_only mode and check the scheme of the current URL
2136        if self.inner.https_only && url.scheme() != "https" {
2137            return Pending::new_err(error::url_bad_scheme(url));
2138        }
2139
2140        // insert default headers in the request headers
2141        // without overwriting already appended headers.
2142        for (key, value) in &self.inner.headers {
2143            if let Entry::Vacant(entry) = headers.entry(key) {
2144                entry.insert(value.clone());
2145            }
2146        }
2147
2148        // Add cookies from the cookie store.
2149        #[cfg(feature = "cookies")]
2150        {
2151            if let Some(cookie_store) = self.inner.cookie_store.as_ref() {
2152                if headers.get(crate::header::COOKIE).is_none() {
2153                    add_cookie_header(&mut headers, &**cookie_store, &url);
2154                }
2155            }
2156        }
2157
2158        let accept_encoding = self.inner.accepts.as_str();
2159
2160        if let Some(accept_encoding) = accept_encoding {
2161            if !headers.contains_key(ACCEPT_ENCODING) && !headers.contains_key(RANGE) {
2162                headers.insert(ACCEPT_ENCODING, HeaderValue::from_static(accept_encoding));
2163            }
2164        }
2165
2166        let uri = match try_uri(&url) {
2167            Ok(uri) => uri,
2168            _ => return Pending::new_err(error::url_invalid_uri(url)),
2169        };
2170
2171        let (reusable, body) = match body {
2172            Some(body) => {
2173                let (reusable, body) = body.try_reuse();
2174                (Some(reusable), body)
2175            }
2176            None => (None, Body::empty()),
2177        };
2178
2179        self.proxy_auth(&uri, &mut headers);
2180
2181        let builder = hyper::Request::builder()
2182            .method(method.clone())
2183            .uri(uri)
2184            .version(version);
2185
2186        let in_flight = match version {
2187            #[cfg(feature = "http3")]
2188            http::Version::HTTP_3 if self.inner.h3_client.is_some() => {
2189                let mut req = builder.body(body).expect("valid request parts");
2190                *req.headers_mut() = headers.clone();
2191                ResponseFuture::H3(self.inner.h3_client.as_ref().unwrap().request(req))
2192            }
2193            _ => {
2194                let mut req = builder.body(body).expect("valid request parts");
2195                *req.headers_mut() = headers.clone();
2196                ResponseFuture::Default(self.inner.hyper.request(req))
2197            }
2198        };
2199
2200        let total_timeout = timeout
2201            .or(self.inner.request_timeout)
2202            .map(tokio::time::sleep)
2203            .map(Box::pin);
2204
2205        let read_timeout_fut = self
2206            .inner
2207            .read_timeout
2208            .map(tokio::time::sleep)
2209            .map(Box::pin);
2210
2211        Pending {
2212            inner: PendingInner::Request(PendingRequest {
2213                method,
2214                url,
2215                headers,
2216                body: reusable,
2217
2218                urls: Vec::new(),
2219
2220                retry_count: 0,
2221
2222                client: self.inner.clone(),
2223
2224                in_flight,
2225                total_timeout,
2226                read_timeout_fut,
2227                read_timeout: self.inner.read_timeout,
2228            }),
2229        }
2230    }
2231
2232    fn proxy_auth(&self, dst: &Uri, headers: &mut HeaderMap) {
2233        if !self.inner.proxies_maybe_http_auth {
2234            return;
2235        }
2236
2237        // Only set the header here if the destination scheme is 'http',
2238        // since otherwise, the header will be included in the CONNECT tunnel
2239        // request instead.
2240        if dst.scheme() != Some(&Scheme::HTTP) {
2241            return;
2242        }
2243
2244        if headers.contains_key(PROXY_AUTHORIZATION) {
2245            return;
2246        }
2247
2248        for proxy in self.inner.proxies.iter() {
2249            if proxy.is_match(dst) {
2250                if let Some(header) = proxy.http_basic_auth(dst) {
2251                    headers.insert(PROXY_AUTHORIZATION, header);
2252                }
2253
2254                break;
2255            }
2256        }
2257    }
2258}
2259
2260impl fmt::Debug for Client {
2261    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2262        let mut builder = f.debug_struct("Client");
2263        self.inner.fmt_fields(&mut builder);
2264        builder.finish()
2265    }
2266}
2267
2268impl tower_service::Service<Request> for Client {
2269    type Response = Response;
2270    type Error = crate::Error;
2271    type Future = Pending;
2272
2273    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
2274        Poll::Ready(Ok(()))
2275    }
2276
2277    fn call(&mut self, req: Request) -> Self::Future {
2278        self.execute_request(req)
2279    }
2280}
2281
2282impl tower_service::Service<Request> for &'_ Client {
2283    type Response = Response;
2284    type Error = crate::Error;
2285    type Future = Pending;
2286
2287    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
2288        Poll::Ready(Ok(()))
2289    }
2290
2291    fn call(&mut self, req: Request) -> Self::Future {
2292        self.execute_request(req)
2293    }
2294}
2295
2296impl fmt::Debug for ClientBuilder {
2297    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2298        let mut builder = f.debug_struct("ClientBuilder");
2299        self.config.fmt_fields(&mut builder);
2300        builder.finish()
2301    }
2302}
2303
2304impl Config {
2305    fn fmt_fields(&self, f: &mut fmt::DebugStruct<'_, '_>) {
2306        // Instead of deriving Debug, only print fields when their output
2307        // would provide relevant or interesting data.
2308
2309        #[cfg(feature = "cookies")]
2310        {
2311            if let Some(_) = self.cookie_store {
2312                f.field("cookie_store", &true);
2313            }
2314        }
2315
2316        f.field("accepts", &self.accepts);
2317
2318        if !self.proxies.is_empty() {
2319            f.field("proxies", &self.proxies);
2320        }
2321
2322        if !self.redirect_policy.is_default() {
2323            f.field("redirect_policy", &self.redirect_policy);
2324        }
2325
2326        if self.referer {
2327            f.field("referer", &true);
2328        }
2329
2330        f.field("default_headers", &self.headers);
2331
2332        if self.http1_title_case_headers {
2333            f.field("http1_title_case_headers", &true);
2334        }
2335
2336        if self.http1_allow_obsolete_multiline_headers_in_responses {
2337            f.field("http1_allow_obsolete_multiline_headers_in_responses", &true);
2338        }
2339
2340        if self.http1_ignore_invalid_headers_in_responses {
2341            f.field("http1_ignore_invalid_headers_in_responses", &true);
2342        }
2343
2344        if self.http1_allow_spaces_after_header_name_in_responses {
2345            f.field("http1_allow_spaces_after_header_name_in_responses", &true);
2346        }
2347
2348        if matches!(self.http_version_pref, HttpVersionPref::Http1) {
2349            f.field("http1_only", &true);
2350        }
2351
2352        #[cfg(feature = "http2")]
2353        if matches!(self.http_version_pref, HttpVersionPref::Http2) {
2354            f.field("http2_prior_knowledge", &true);
2355        }
2356
2357        if let Some(ref d) = self.connect_timeout {
2358            f.field("connect_timeout", d);
2359        }
2360
2361        if let Some(ref d) = self.timeout {
2362            f.field("timeout", d);
2363        }
2364
2365        if let Some(ref v) = self.local_address {
2366            f.field("local_address", v);
2367        }
2368
2369        #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
2370        if let Some(ref v) = self.interface {
2371            f.field("interface", v);
2372        }
2373
2374        if self.nodelay {
2375            f.field("tcp_nodelay", &true);
2376        }
2377
2378        #[cfg(feature = "__tls")]
2379        {
2380            if !self.hostname_verification {
2381                f.field("danger_accept_invalid_hostnames", &true);
2382            }
2383        }
2384
2385        #[cfg(feature = "__tls")]
2386        {
2387            if !self.certs_verification {
2388                f.field("danger_accept_invalid_certs", &true);
2389            }
2390
2391            if let Some(ref min_tls_version) = self.min_tls_version {
2392                f.field("min_tls_version", min_tls_version);
2393            }
2394
2395            if let Some(ref max_tls_version) = self.max_tls_version {
2396                f.field("max_tls_version", max_tls_version);
2397            }
2398
2399            f.field("tls_sni", &self.tls_sni);
2400
2401            f.field("tls_info", &self.tls_info);
2402        }
2403
2404        #[cfg(all(feature = "default-tls", feature = "__rustls"))]
2405        {
2406            f.field("tls_backend", &self.tls);
2407        }
2408
2409        if !self.dns_overrides.is_empty() {
2410            f.field("dns_overrides", &self.dns_overrides);
2411        }
2412
2413        #[cfg(feature = "http3")]
2414        {
2415            if self.tls_enable_early_data {
2416                f.field("tls_enable_early_data", &true);
2417            }
2418        }
2419    }
2420}
2421
2422struct ClientRef {
2423    accepts: Accepts,
2424    #[cfg(feature = "cookies")]
2425    cookie_store: Option<Arc<dyn cookie::CookieStore>>,
2426    headers: HeaderMap,
2427    hyper: HyperClient,
2428    #[cfg(feature = "http3")]
2429    h3_client: Option<H3Client>,
2430    redirect_policy: redirect::Policy,
2431    referer: bool,
2432    request_timeout: Option<Duration>,
2433    read_timeout: Option<Duration>,
2434    proxies: Arc<Vec<Proxy>>,
2435    proxies_maybe_http_auth: bool,
2436    https_only: bool,
2437}
2438
2439impl ClientRef {
2440    fn fmt_fields(&self, f: &mut fmt::DebugStruct<'_, '_>) {
2441        // Instead of deriving Debug, only print fields when their output
2442        // would provide relevant or interesting data.
2443
2444        #[cfg(feature = "cookies")]
2445        {
2446            if let Some(_) = self.cookie_store {
2447                f.field("cookie_store", &true);
2448            }
2449        }
2450
2451        f.field("accepts", &self.accepts);
2452
2453        if !self.proxies.is_empty() {
2454            f.field("proxies", &self.proxies);
2455        }
2456
2457        if !self.redirect_policy.is_default() {
2458            f.field("redirect_policy", &self.redirect_policy);
2459        }
2460
2461        if self.referer {
2462            f.field("referer", &true);
2463        }
2464
2465        f.field("default_headers", &self.headers);
2466
2467        if let Some(ref d) = self.request_timeout {
2468            f.field("timeout", d);
2469        }
2470
2471        if let Some(ref d) = self.read_timeout {
2472            f.field("read_timeout", d);
2473        }
2474    }
2475}
2476
2477pin_project! {
2478    pub struct Pending {
2479        #[pin]
2480        inner: PendingInner,
2481    }
2482}
2483
2484enum PendingInner {
2485    Request(PendingRequest),
2486    Error(Option<crate::Error>),
2487}
2488
2489pin_project! {
2490    struct PendingRequest {
2491        method: Method,
2492        url: Url,
2493        headers: HeaderMap,
2494        body: Option<Option<Bytes>>,
2495
2496        urls: Vec<Url>,
2497
2498        retry_count: usize,
2499
2500        client: Arc<ClientRef>,
2501
2502        #[pin]
2503        in_flight: ResponseFuture,
2504        #[pin]
2505        total_timeout: Option<Pin<Box<Sleep>>>,
2506        #[pin]
2507        read_timeout_fut: Option<Pin<Box<Sleep>>>,
2508        read_timeout: Option<Duration>,
2509    }
2510}
2511
2512enum ResponseFuture {
2513    Default(HyperResponseFuture),
2514    #[cfg(feature = "http3")]
2515    H3(H3ResponseFuture),
2516}
2517
2518impl PendingRequest {
2519    fn in_flight(self: Pin<&mut Self>) -> Pin<&mut ResponseFuture> {
2520        self.project().in_flight
2521    }
2522
2523    fn total_timeout(self: Pin<&mut Self>) -> Pin<&mut Option<Pin<Box<Sleep>>>> {
2524        self.project().total_timeout
2525    }
2526
2527    fn read_timeout(self: Pin<&mut Self>) -> Pin<&mut Option<Pin<Box<Sleep>>>> {
2528        self.project().read_timeout_fut
2529    }
2530
2531    fn urls(self: Pin<&mut Self>) -> &mut Vec<Url> {
2532        self.project().urls
2533    }
2534
2535    fn headers(self: Pin<&mut Self>) -> &mut HeaderMap {
2536        self.project().headers
2537    }
2538
2539    #[cfg(any(feature = "http2", feature = "http3"))]
2540    fn retry_error(mut self: Pin<&mut Self>, err: &(dyn std::error::Error + 'static)) -> bool {
2541        use log::trace;
2542
2543        if !is_retryable_error(err) {
2544            return false;
2545        }
2546
2547        trace!("can retry {err:?}");
2548
2549        let body = match self.body {
2550            Some(Some(ref body)) => Body::reusable(body.clone()),
2551            Some(None) => {
2552                debug!("error was retryable, but body not reusable");
2553                return false;
2554            }
2555            None => Body::empty(),
2556        };
2557
2558        if self.retry_count >= 2 {
2559            trace!("retry count too high");
2560            return false;
2561        }
2562        self.retry_count += 1;
2563
2564        // If it parsed once, it should parse again
2565        let uri = try_uri(&self.url).expect("URL was already validated as URI");
2566
2567        *self.as_mut().in_flight().get_mut() = match *self.as_mut().in_flight().as_ref() {
2568            #[cfg(feature = "http3")]
2569            ResponseFuture::H3(_) => {
2570                let mut req = hyper::Request::builder()
2571                    .method(self.method.clone())
2572                    .uri(uri)
2573                    .body(body)
2574                    .expect("valid request parts");
2575                *req.headers_mut() = self.headers.clone();
2576                ResponseFuture::H3(
2577                    self.client
2578                        .h3_client
2579                        .as_ref()
2580                        .expect("H3 client must exists, otherwise we can't have a h3 request here")
2581                        .request(req),
2582                )
2583            }
2584            _ => {
2585                let mut req = hyper::Request::builder()
2586                    .method(self.method.clone())
2587                    .uri(uri)
2588                    .body(body)
2589                    .expect("valid request parts");
2590                *req.headers_mut() = self.headers.clone();
2591                ResponseFuture::Default(self.client.hyper.request(req))
2592            }
2593        };
2594
2595        true
2596    }
2597}
2598
2599#[cfg(any(feature = "http2", feature = "http3"))]
2600fn is_retryable_error(err: &(dyn std::error::Error + 'static)) -> bool {
2601    // pop the legacy::Error
2602    let err = if let Some(err) = err.source() {
2603        err
2604    } else {
2605        return false;
2606    };
2607
2608    #[cfg(feature = "http3")]
2609    if let Some(cause) = err.source() {
2610        if let Some(err) = cause.downcast_ref::<h3::Error>() {
2611            debug!("determining if HTTP/3 error {err} can be retried");
2612            // TODO: Does h3 provide an API for checking the error?
2613            return err.to_string().as_str() == "timeout";
2614        }
2615    }
2616
2617    #[cfg(feature = "http2")]
2618    if let Some(cause) = err.source() {
2619        if let Some(err) = cause.downcast_ref::<h2::Error>() {
2620            // They sent us a graceful shutdown, try with a new connection!
2621            if err.is_go_away() && err.is_remote() && err.reason() == Some(h2::Reason::NO_ERROR) {
2622                return true;
2623            }
2624
2625            // REFUSED_STREAM was sent from the server, which is safe to retry.
2626            // https://www.rfc-editor.org/rfc/rfc9113.html#section-8.7-3.2
2627            if err.is_reset() && err.is_remote() && err.reason() == Some(h2::Reason::REFUSED_STREAM)
2628            {
2629                return true;
2630            }
2631        }
2632    }
2633    false
2634}
2635
2636impl Pending {
2637    pub(super) fn new_err(err: crate::Error) -> Pending {
2638        Pending {
2639            inner: PendingInner::Error(Some(err)),
2640        }
2641    }
2642
2643    fn inner(self: Pin<&mut Self>) -> Pin<&mut PendingInner> {
2644        self.project().inner
2645    }
2646}
2647
2648impl Future for Pending {
2649    type Output = Result<Response, crate::Error>;
2650
2651    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
2652        let inner = self.inner();
2653        match inner.get_mut() {
2654            PendingInner::Request(ref mut req) => Pin::new(req).poll(cx),
2655            PendingInner::Error(ref mut err) => Poll::Ready(Err(err
2656                .take()
2657                .expect("Pending error polled more than once"))),
2658        }
2659    }
2660}
2661
2662impl Future for PendingRequest {
2663    type Output = Result<Response, crate::Error>;
2664
2665    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
2666        if let Some(delay) = self.as_mut().total_timeout().as_mut().as_pin_mut() {
2667            if let Poll::Ready(()) = delay.poll(cx) {
2668                return Poll::Ready(Err(
2669                    crate::error::request(crate::error::TimedOut).with_url(self.url.clone())
2670                ));
2671            }
2672        }
2673
2674        if let Some(delay) = self.as_mut().read_timeout().as_mut().as_pin_mut() {
2675            if let Poll::Ready(()) = delay.poll(cx) {
2676                return Poll::Ready(Err(
2677                    crate::error::request(crate::error::TimedOut).with_url(self.url.clone())
2678                ));
2679            }
2680        }
2681
2682        loop {
2683            let res = match self.as_mut().in_flight().get_mut() {
2684                ResponseFuture::Default(r) => match Pin::new(r).poll(cx) {
2685                    Poll::Ready(Err(e)) => {
2686                        #[cfg(feature = "http2")]
2687                        if self.as_mut().retry_error(&e) {
2688                            continue;
2689                        }
2690                        return Poll::Ready(Err(
2691                            crate::error::request(e).with_url(self.url.clone())
2692                        ));
2693                    }
2694                    Poll::Ready(Ok(res)) => res.map(super::body::boxed),
2695                    Poll::Pending => return Poll::Pending,
2696                },
2697                #[cfg(feature = "http3")]
2698                ResponseFuture::H3(r) => match Pin::new(r).poll(cx) {
2699                    Poll::Ready(Err(e)) => {
2700                        if self.as_mut().retry_error(&e) {
2701                            continue;
2702                        }
2703                        return Poll::Ready(Err(
2704                            crate::error::request(e).with_url(self.url.clone())
2705                        ));
2706                    }
2707                    Poll::Ready(Ok(res)) => res,
2708                    Poll::Pending => return Poll::Pending,
2709                },
2710            };
2711
2712            #[cfg(feature = "cookies")]
2713            {
2714                if let Some(ref cookie_store) = self.client.cookie_store {
2715                    let mut cookies =
2716                        cookie::extract_response_cookie_headers(&res.headers()).peekable();
2717                    if cookies.peek().is_some() {
2718                        cookie_store.set_cookies(&mut cookies, &self.url);
2719                    }
2720                }
2721            }
2722            let should_redirect = match res.status() {
2723                StatusCode::MOVED_PERMANENTLY | StatusCode::FOUND | StatusCode::SEE_OTHER => {
2724                    self.body = None;
2725                    for header in &[
2726                        TRANSFER_ENCODING,
2727                        CONTENT_ENCODING,
2728                        CONTENT_TYPE,
2729                        CONTENT_LENGTH,
2730                    ] {
2731                        self.headers.remove(header);
2732                    }
2733
2734                    match self.method {
2735                        Method::GET | Method::HEAD => {}
2736                        _ => {
2737                            self.method = Method::GET;
2738                        }
2739                    }
2740                    true
2741                }
2742                StatusCode::TEMPORARY_REDIRECT | StatusCode::PERMANENT_REDIRECT => {
2743                    match self.body {
2744                        Some(Some(_)) | None => true,
2745                        Some(None) => false,
2746                    }
2747                }
2748                _ => false,
2749            };
2750            if should_redirect {
2751                let loc = res.headers().get(LOCATION).and_then(|val| {
2752                    let loc = (|| -> Option<Url> {
2753                        // Some sites may send a UTF-8 Location header,
2754                        // even though we're supposed to treat those bytes
2755                        // as opaque, we'll check specifically for utf8.
2756                        self.url.join(str::from_utf8(val.as_bytes()).ok()?).ok()
2757                    })();
2758
2759                    // Check that the `url` is also a valid `http::Uri`.
2760                    //
2761                    // If not, just log it and skip the redirect.
2762                    let loc = loc.and_then(|url| {
2763                        if try_uri(&url).is_ok() {
2764                            Some(url)
2765                        } else {
2766                            None
2767                        }
2768                    });
2769
2770                    if loc.is_none() {
2771                        debug!("Location header had invalid URI: {val:?}");
2772                    }
2773                    loc
2774                });
2775                if let Some(loc) = loc {
2776                    if self.client.referer {
2777                        if let Some(referer) = make_referer(&loc, &self.url) {
2778                            self.headers.insert(REFERER, referer);
2779                        }
2780                    }
2781                    let url = self.url.clone();
2782                    self.as_mut().urls().push(url);
2783                    let action = self
2784                        .client
2785                        .redirect_policy
2786                        .check(res.status(), &loc, &self.urls);
2787
2788                    match action {
2789                        redirect::ActionKind::Follow => {
2790                            debug!("redirecting '{}' to '{}'", self.url, loc);
2791
2792                            if loc.scheme() != "http" && loc.scheme() != "https" {
2793                                return Poll::Ready(Err(error::url_bad_scheme(loc)));
2794                            }
2795
2796                            if self.client.https_only && loc.scheme() != "https" {
2797                                return Poll::Ready(Err(error::redirect(
2798                                    error::url_bad_scheme(loc.clone()),
2799                                    loc,
2800                                )));
2801                            }
2802
2803                            self.url = loc;
2804                            let mut headers =
2805                                std::mem::replace(self.as_mut().headers(), HeaderMap::new());
2806
2807                            remove_sensitive_headers(&mut headers, &self.url, &self.urls);
2808                            let uri = try_uri(&self.url)?;
2809                            let body = match self.body {
2810                                Some(Some(ref body)) => Body::reusable(body.clone()),
2811                                _ => Body::empty(),
2812                            };
2813
2814                            // Add cookies from the cookie store.
2815                            #[cfg(feature = "cookies")]
2816                            {
2817                                if let Some(ref cookie_store) = self.client.cookie_store {
2818                                    add_cookie_header(&mut headers, &**cookie_store, &self.url);
2819                                }
2820                            }
2821
2822                            *self.as_mut().in_flight().get_mut() =
2823                                match *self.as_mut().in_flight().as_ref() {
2824                                    #[cfg(feature = "http3")]
2825                                    ResponseFuture::H3(_) => {
2826                                        let mut req = hyper::Request::builder()
2827                                            .method(self.method.clone())
2828                                            .uri(uri.clone())
2829                                            .body(body)
2830                                            .expect("valid request parts");
2831                                        *req.headers_mut() = headers.clone();
2832                                        std::mem::swap(self.as_mut().headers(), &mut headers);
2833                                        ResponseFuture::H3(self.client.h3_client
2834                        .as_ref()
2835                        .expect("H3 client must exists, otherwise we can't have a h3 request here")
2836                                            .request(req))
2837                                    }
2838                                    _ => {
2839                                        let mut req = hyper::Request::builder()
2840                                            .method(self.method.clone())
2841                                            .uri(uri.clone())
2842                                            .body(body)
2843                                            .expect("valid request parts");
2844                                        *req.headers_mut() = headers.clone();
2845                                        std::mem::swap(self.as_mut().headers(), &mut headers);
2846                                        ResponseFuture::Default(self.client.hyper.request(req))
2847                                    }
2848                                };
2849
2850                            continue;
2851                        }
2852                        redirect::ActionKind::Stop => {
2853                            debug!("redirect policy disallowed redirection to '{loc}'");
2854                        }
2855                        redirect::ActionKind::Error(err) => {
2856                            return Poll::Ready(Err(crate::error::redirect(err, self.url.clone())));
2857                        }
2858                    }
2859                }
2860            }
2861
2862            let res = Response::new(
2863                res,
2864                self.url.clone(),
2865                self.client.accepts,
2866                self.total_timeout.take(),
2867                self.read_timeout,
2868            );
2869            return Poll::Ready(Ok(res));
2870        }
2871    }
2872}
2873
2874impl fmt::Debug for Pending {
2875    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2876        match self.inner {
2877            PendingInner::Request(ref req) => f
2878                .debug_struct("Pending")
2879                .field("method", &req.method)
2880                .field("url", &req.url)
2881                .finish(),
2882            PendingInner::Error(ref err) => f.debug_struct("Pending").field("error", err).finish(),
2883        }
2884    }
2885}
2886
2887fn make_referer(next: &Url, previous: &Url) -> Option<HeaderValue> {
2888    if next.scheme() == "http" && previous.scheme() == "https" {
2889        return None;
2890    }
2891
2892    let mut referer = previous.clone();
2893    let _ = referer.set_username("");
2894    let _ = referer.set_password(None);
2895    referer.set_fragment(None);
2896    referer.as_str().parse().ok()
2897}
2898
2899#[cfg(feature = "cookies")]
2900fn add_cookie_header(headers: &mut HeaderMap, cookie_store: &dyn cookie::CookieStore, url: &Url) {
2901    if let Some(header) = cookie_store.cookies(url) {
2902        headers.insert(crate::header::COOKIE, header);
2903    }
2904}
2905
2906#[cfg(test)]
2907mod tests {
2908    #![cfg(not(feature = "rustls-tls-manual-roots-no-provider"))]
2909
2910    #[tokio::test]
2911    async fn execute_request_rejects_invalid_urls() {
2912        let url_str = "hxxps://www.rust-lang.org/";
2913        let url = url::Url::parse(url_str).unwrap();
2914        let result = crate::get(url.clone()).await;
2915
2916        assert!(result.is_err());
2917        let err = result.err().unwrap();
2918        assert!(err.is_builder());
2919        assert_eq!(url_str, err.url().unwrap().as_str());
2920    }
2921
2922    /// https://github.com/seanmonstar/reqwest/issues/668
2923    #[tokio::test]
2924    async fn execute_request_rejects_invalid_hostname() {
2925        let url_str = "https://{{hostname}}/";
2926        let url = url::Url::parse(url_str).unwrap();
2927        let result = crate::get(url.clone()).await;
2928
2929        assert!(result.is_err());
2930        let err = result.err().unwrap();
2931        assert!(err.is_builder());
2932        assert_eq!(url_str, err.url().unwrap().as_str());
2933    }
2934}