1 #[cfg(any(feature = "native-tls", feature = "__rustls",))]
2 use std::any::Any;
3 use std::net::IpAddr;
4 use std::sync::Arc;
5 use std::time::Duration;
6 use std::{collections::HashMap, convert::TryInto, net::SocketAddr};
7 use std::{fmt, str};
8 
9 use bytes::Bytes;
10 use http::header::{
11     Entry, HeaderMap, HeaderValue, ACCEPT, ACCEPT_ENCODING, CONTENT_ENCODING, CONTENT_LENGTH,
12     CONTENT_TYPE, LOCATION, PROXY_AUTHORIZATION, RANGE, REFERER, TRANSFER_ENCODING, USER_AGENT,
13 };
14 use http::uri::Scheme;
15 use http::Uri;
16 use hyper::client::ResponseFuture;
17 #[cfg(feature = "native-tls-crate")]
18 use native_tls_crate::TlsConnector;
19 use pin_project_lite::pin_project;
20 use std::future::Future;
21 use std::pin::Pin;
22 use std::task::{Context, Poll};
23 use tokio::time::Sleep;
24 
25 use log::debug;
26 
27 use super::decoder::Accepts;
28 use super::request::{Request, RequestBuilder};
29 use super::response::Response;
30 use super::Body;
31 use crate::connect::{Connector, HttpConnector};
32 #[cfg(feature = "cookies")]
33 use crate::cookie;
34 use crate::error;
35 use crate::into_url::{expect_uri, try_uri};
36 use crate::redirect::{self, remove_sensitive_headers};
37 #[cfg(feature = "__tls")]
38 use crate::tls::{self, TlsBackend};
39 #[cfg(feature = "__tls")]
40 use crate::Certificate;
41 #[cfg(any(feature = "native-tls", feature = "__rustls"))]
42 use crate::Identity;
43 use crate::{IntoUrl, Method, Proxy, StatusCode, Url};
44 
45 /// An asynchronous `Client` to make Requests with.
46 ///
47 /// The Client has various configuration values to tweak, but the defaults
48 /// are set to what is usually the most commonly desired value. To configure a
49 /// `Client`, use `Client::builder()`.
50 ///
51 /// The `Client` holds a connection pool internally, so it is advised that
52 /// you create one and **reuse** it.
53 ///
54 /// You do **not** have to wrap the `Client` in an [`Rc`] or [`Arc`] to **reuse** it,
55 /// because it already uses an [`Arc`] internally.
56 ///
57 /// [`Rc`]: std::rc::Rc
58 #[derive(Clone)]
59 pub struct Client {
60     inner: Arc<ClientRef>,
61 }
62 
63 /// A `ClientBuilder` can be used to create a `Client` with custom configuration.
64 #[must_use]
65 pub struct ClientBuilder {
66     config: Config,
67 }
68 
69 enum HttpVersionPref {
70     Http1,
71     Http2,
72     All,
73 }
74 
75 struct Config {
76     // NOTE: When adding a new field, update `fmt::Debug for ClientBuilder`
77     accepts: Accepts,
78     headers: HeaderMap,
79     #[cfg(feature = "native-tls")]
80     hostname_verification: bool,
81     #[cfg(feature = "__tls")]
82     certs_verification: bool,
83     connect_timeout: Option<Duration>,
84     connection_verbose: bool,
85     pool_idle_timeout: Option<Duration>,
86     pool_max_idle_per_host: usize,
87     tcp_keepalive: Option<Duration>,
88     #[cfg(any(feature = "native-tls", feature = "__rustls"))]
89     identity: Option<Identity>,
90     proxies: Vec<Proxy>,
91     auto_sys_proxy: bool,
92     redirect_policy: redirect::Policy,
93     referer: bool,
94     timeout: Option<Duration>,
95     #[cfg(feature = "__tls")]
96     root_certs: Vec<Certificate>,
97     #[cfg(feature = "__tls")]
98     tls_built_in_root_certs: bool,
99     #[cfg(feature = "__tls")]
100     min_tls_version: Option<tls::Version>,
101     #[cfg(feature = "__tls")]
102     max_tls_version: Option<tls::Version>,
103     #[cfg(feature = "__tls")]
104     tls: TlsBackend,
105     http_version_pref: HttpVersionPref,
106     http1_title_case_headers: bool,
107     http2_initial_stream_window_size: Option<u32>,
108     http2_initial_connection_window_size: Option<u32>,
109     http2_adaptive_window: bool,
110     http2_max_frame_size: Option<u32>,
111     local_address: Option<IpAddr>,
112     nodelay: bool,
113     #[cfg(feature = "cookies")]
114     cookie_store: Option<Arc<dyn cookie::CookieStore>>,
115     trust_dns: bool,
116     error: Option<crate::Error>,
117     https_only: bool,
118     dns_overrides: HashMap<String, SocketAddr>,
119 }
120 
121 impl Default for ClientBuilder {
default() -> Self122     fn default() -> Self {
123         Self::new()
124     }
125 }
126 
127 impl ClientBuilder {
128     /// Constructs a new `ClientBuilder`.
129     ///
130     /// This is the same as `Client::builder()`.
new() -> ClientBuilder131     pub fn new() -> ClientBuilder {
132         let mut headers: HeaderMap<HeaderValue> = HeaderMap::with_capacity(2);
133         headers.insert(ACCEPT, HeaderValue::from_static("*/*"));
134 
135         ClientBuilder {
136             config: Config {
137                 error: None,
138                 accepts: Accepts::default(),
139                 headers,
140                 #[cfg(feature = "native-tls")]
141                 hostname_verification: true,
142                 #[cfg(feature = "__tls")]
143                 certs_verification: true,
144                 connect_timeout: None,
145                 connection_verbose: false,
146                 pool_idle_timeout: Some(Duration::from_secs(90)),
147                 pool_max_idle_per_host: std::usize::MAX,
148                 // TODO: Re-enable default duration once hyper's HttpConnector is fixed
149                 // to no longer error when an option fails.
150                 tcp_keepalive: None, //Some(Duration::from_secs(60)),
151                 proxies: Vec::new(),
152                 auto_sys_proxy: true,
153                 redirect_policy: redirect::Policy::default(),
154                 referer: true,
155                 timeout: None,
156                 #[cfg(feature = "__tls")]
157                 root_certs: Vec::new(),
158                 #[cfg(feature = "__tls")]
159                 tls_built_in_root_certs: true,
160                 #[cfg(any(feature = "native-tls", feature = "__rustls"))]
161                 identity: None,
162                 #[cfg(feature = "__tls")]
163                 min_tls_version: None,
164                 #[cfg(feature = "__tls")]
165                 max_tls_version: None,
166                 #[cfg(feature = "__tls")]
167                 tls: TlsBackend::default(),
168                 http_version_pref: HttpVersionPref::All,
169                 http1_title_case_headers: false,
170                 http2_initial_stream_window_size: None,
171                 http2_initial_connection_window_size: None,
172                 http2_adaptive_window: false,
173                 http2_max_frame_size: None,
174                 local_address: None,
175                 nodelay: true,
176                 trust_dns: cfg!(feature = "trust-dns"),
177                 #[cfg(feature = "cookies")]
178                 cookie_store: None,
179                 https_only: false,
180                 dns_overrides: HashMap::new(),
181             },
182         }
183     }
184 
185     /// Returns a `Client` that uses this `ClientBuilder` configuration.
186     ///
187     /// # Errors
188     ///
189     /// This method fails if a TLS backend cannot be initialized, or the resolver
190     /// cannot load the system configuration.
build(self) -> crate::Result<Client>191     pub fn build(self) -> crate::Result<Client> {
192         let config = self.config;
193 
194         if let Some(err) = config.error {
195             return Err(err);
196         }
197 
198         let mut proxies = config.proxies;
199         if config.auto_sys_proxy {
200             proxies.push(Proxy::system());
201         }
202         let proxies = Arc::new(proxies);
203 
204         let mut connector = {
205             #[cfg(feature = "__tls")]
206             fn user_agent(headers: &HeaderMap) -> Option<HeaderValue> {
207                 headers.get(USER_AGENT).cloned()
208             }
209 
210             let http = match config.trust_dns {
211                 false => {
212                     if config.dns_overrides.is_empty() {
213                         HttpConnector::new_gai()
214                     } else {
215                         HttpConnector::new_gai_with_overrides(config.dns_overrides)
216                     }
217                 }
218                 #[cfg(feature = "trust-dns")]
219                 true => {
220                     if config.dns_overrides.is_empty() {
221                         HttpConnector::new_trust_dns()?
222                     } else {
223                         HttpConnector::new_trust_dns_with_overrides(config.dns_overrides)?
224                     }
225                 }
226                 #[cfg(not(feature = "trust-dns"))]
227                 true => unreachable!("trust-dns shouldn't be enabled unless the feature is"),
228             };
229 
230             #[cfg(feature = "__tls")]
231             match config.tls {
232                 #[cfg(feature = "default-tls")]
233                 TlsBackend::Default => {
234                     let mut tls = TlsConnector::builder();
235 
236                     #[cfg(feature = "native-tls-alpn")]
237                     {
238                         match config.http_version_pref {
239                             HttpVersionPref::Http1 => {
240                                 tls.request_alpns(&["http/1.1"]);
241                             }
242                             HttpVersionPref::Http2 => {
243                                 tls.request_alpns(&["h2"]);
244                             }
245                             HttpVersionPref::All => {
246                                 tls.request_alpns(&["h2", "http/1.1"]);
247                             }
248                         }
249                     }
250 
251                     #[cfg(feature = "native-tls")]
252                     {
253                         tls.danger_accept_invalid_hostnames(!config.hostname_verification);
254                     }
255 
256                     tls.danger_accept_invalid_certs(!config.certs_verification);
257 
258                     tls.disable_built_in_roots(!config.tls_built_in_root_certs);
259 
260                     for cert in config.root_certs {
261                         cert.add_to_native_tls(&mut tls);
262                     }
263 
264                     #[cfg(feature = "native-tls")]
265                     {
266                         if let Some(id) = config.identity {
267                             id.add_to_native_tls(&mut tls)?;
268                         }
269                     }
270 
271                     if let Some(min_tls_version) = config.min_tls_version {
272                         let protocol = min_tls_version.to_native_tls().ok_or_else(|| {
273                             // TLS v1.3. This would be entirely reasonable,
274                             // native-tls just doesn't support it.
275                             // https://github.com/sfackler/rust-native-tls/issues/140
276                             crate::error::builder("invalid minimum TLS version for backend")
277                         })?;
278                         tls.min_protocol_version(Some(protocol));
279                     }
280 
281                     if let Some(max_tls_version) = config.max_tls_version {
282                         let protocol = max_tls_version.to_native_tls().ok_or_else(|| {
283                             // TLS v1.3.
284                             // We could arguably do max_protocol_version(None), given
285                             // that 1.4 does not exist yet, but that'd get messy in the
286                             // future.
287                             crate::error::builder("invalid maximum TLS version for backend")
288                         })?;
289                         tls.max_protocol_version(Some(protocol));
290                     }
291 
292                     Connector::new_default_tls(
293                         http,
294                         tls,
295                         proxies.clone(),
296                         user_agent(&config.headers),
297                         config.local_address,
298                         config.nodelay,
299                     )?
300                 }
301                 #[cfg(feature = "native-tls")]
302                 TlsBackend::BuiltNativeTls(conn) => Connector::from_built_default_tls(
303                     http,
304                     conn,
305                     proxies.clone(),
306                     user_agent(&config.headers),
307                     config.local_address,
308                     config.nodelay,
309                 ),
310                 #[cfg(feature = "__rustls")]
311                 TlsBackend::BuiltRustls(conn) => Connector::new_rustls_tls(
312                     http,
313                     conn,
314                     proxies.clone(),
315                     user_agent(&config.headers),
316                     config.local_address,
317                     config.nodelay,
318                 ),
319                 #[cfg(feature = "__rustls")]
320                 TlsBackend::Rustls => {
321                     use crate::tls::NoVerifier;
322 
323                     // Set root certificates.
324                     let mut root_cert_store = rustls::RootCertStore::empty();
325                     for cert in config.root_certs {
326                         cert.add_to_rustls(&mut root_cert_store)?;
327                     }
328 
329                     #[cfg(feature = "rustls-tls-webpki-roots")]
330                     if config.tls_built_in_root_certs {
331                         use rustls::OwnedTrustAnchor;
332 
333                         let trust_anchors =
334                             webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|trust_anchor| {
335                                 OwnedTrustAnchor::from_subject_spki_name_constraints(
336                                     trust_anchor.subject,
337                                     trust_anchor.spki,
338                                     trust_anchor.name_constraints,
339                                 )
340                             });
341 
342                         root_cert_store.add_server_trust_anchors(trust_anchors);
343                     }
344 
345                     #[cfg(feature = "rustls-tls-native-roots")]
346                     if config.tls_built_in_root_certs {
347                         for cert in rustls_native_certs::load_native_certs()
348                             .map_err(crate::error::builder)?
349                         {
350                             root_cert_store
351                                 .add(&rustls::Certificate(cert.0))
352                                 .map_err(crate::error::builder)?
353                         }
354                     }
355 
356                     // Set TLS versions.
357                     let mut versions = rustls::ALL_VERSIONS.to_vec();
358 
359                     if let Some(min_tls_version) = config.min_tls_version {
360                         versions.retain(|&supported_version| {
361                             match tls::Version::from_rustls(supported_version.version) {
362                                 Some(version) => version >= min_tls_version,
363                                 // Assume it's so new we don't know about it, allow it
364                                 // (as of writing this is unreachable)
365                                 None => true,
366                             }
367                         });
368                     }
369 
370                     if let Some(max_tls_version) = config.max_tls_version {
371                         versions.retain(|&supported_version| {
372                             match tls::Version::from_rustls(supported_version.version) {
373                                 Some(version) => version <= max_tls_version,
374                                 None => false,
375                             }
376                         });
377                     }
378 
379                     // Build TLS config
380                     let config_builder = rustls::ClientConfig::builder()
381                         .with_safe_default_cipher_suites()
382                         .with_safe_default_kx_groups()
383                         .with_protocol_versions(&versions)
384                         .map_err(crate::error::builder)?
385                         .with_root_certificates(root_cert_store);
386 
387                     // Finalize TLS config
388                     let mut tls = if let Some(id) = config.identity {
389                         id.add_to_rustls(config_builder)?
390                     } else {
391                         config_builder.with_no_client_auth()
392                     };
393 
394                     // Certificate verifier
395                     if !config.certs_verification {
396                         tls.dangerous()
397                             .set_certificate_verifier(Arc::new(NoVerifier));
398                     }
399 
400                     // ALPN protocol
401                     match config.http_version_pref {
402                         HttpVersionPref::Http1 => {
403                             tls.alpn_protocols = vec!["http/1.1".into()];
404                         }
405                         HttpVersionPref::Http2 => {
406                             tls.alpn_protocols = vec!["h2".into()];
407                         }
408                         HttpVersionPref::All => {
409                             tls.alpn_protocols = vec!["h2".into(), "http/1.1".into()];
410                         }
411                     }
412 
413                     Connector::new_rustls_tls(
414                         http,
415                         tls,
416                         proxies.clone(),
417                         user_agent(&config.headers),
418                         config.local_address,
419                         config.nodelay,
420                     )
421                 }
422                 #[cfg(any(feature = "native-tls", feature = "__rustls",))]
423                 TlsBackend::UnknownPreconfigured => {
424                     return Err(crate::error::builder(
425                         "Unknown TLS backend passed to `use_preconfigured_tls`",
426                     ));
427                 }
428             }
429 
430             #[cfg(not(feature = "__tls"))]
431             Connector::new(http, proxies.clone(), config.local_address, config.nodelay)
432         };
433 
434         connector.set_timeout(config.connect_timeout);
435         connector.set_verbose(config.connection_verbose);
436 
437         let mut builder = hyper::Client::builder();
438         if matches!(config.http_version_pref, HttpVersionPref::Http2) {
439             builder.http2_only(true);
440         }
441 
442         if let Some(http2_initial_stream_window_size) = config.http2_initial_stream_window_size {
443             builder.http2_initial_stream_window_size(http2_initial_stream_window_size);
444         }
445         if let Some(http2_initial_connection_window_size) =
446             config.http2_initial_connection_window_size
447         {
448             builder.http2_initial_connection_window_size(http2_initial_connection_window_size);
449         }
450         if config.http2_adaptive_window {
451             builder.http2_adaptive_window(true);
452         }
453         if let Some(http2_max_frame_size) = config.http2_max_frame_size {
454             builder.http2_max_frame_size(http2_max_frame_size);
455         }
456 
457         builder.pool_idle_timeout(config.pool_idle_timeout);
458         builder.pool_max_idle_per_host(config.pool_max_idle_per_host);
459         connector.set_keepalive(config.tcp_keepalive);
460 
461         if config.http1_title_case_headers {
462             builder.http1_title_case_headers(true);
463         }
464 
465         let hyper_client = builder.build(connector);
466 
467         let proxies_maybe_http_auth = proxies.iter().any(|p| p.maybe_has_http_auth());
468 
469         Ok(Client {
470             inner: Arc::new(ClientRef {
471                 accepts: config.accepts,
472                 #[cfg(feature = "cookies")]
473                 cookie_store: config.cookie_store,
474                 hyper: hyper_client,
475                 headers: config.headers,
476                 redirect_policy: config.redirect_policy,
477                 referer: config.referer,
478                 request_timeout: config.timeout,
479                 proxies,
480                 proxies_maybe_http_auth,
481                 https_only: config.https_only,
482             }),
483         })
484     }
485 
486     // Higher-level options
487 
488     /// Sets the `User-Agent` header to be used by this client.
489     ///
490     /// # Example
491     ///
492     /// ```rust
493     /// # async fn doc() -> Result<(), reqwest::Error> {
494     /// // Name your user agent after your app?
495     /// static APP_USER_AGENT: &str = concat!(
496     ///     env!("CARGO_PKG_NAME"),
497     ///     "/",
498     ///     env!("CARGO_PKG_VERSION"),
499     /// );
500     ///
501     /// let client = reqwest::Client::builder()
502     ///     .user_agent(APP_USER_AGENT)
503     ///     .build()?;
504     /// let res = client.get("https://www.rust-lang.org").send().await?;
505     /// # Ok(())
506     /// # }
507     /// ```
user_agent<V>(mut self, value: V) -> ClientBuilder where V: TryInto<HeaderValue>, V::Error: Into<http::Error>,508     pub fn user_agent<V>(mut self, value: V) -> ClientBuilder
509     where
510         V: TryInto<HeaderValue>,
511         V::Error: Into<http::Error>,
512     {
513         match value.try_into() {
514             Ok(value) => {
515                 self.config.headers.insert(USER_AGENT, value);
516             }
517             Err(e) => {
518                 self.config.error = Some(crate::error::builder(e.into()));
519             }
520         };
521         self
522     }
523     /// Sets the default headers for every request.
524     ///
525     /// # Example
526     ///
527     /// ```rust
528     /// use reqwest::header;
529     /// # async fn doc() -> Result<(), reqwest::Error> {
530     /// let mut headers = header::HeaderMap::new();
531     /// headers.insert("X-MY-HEADER", header::HeaderValue::from_static("value"));
532     ///
533     /// // Consider marking security-sensitive headers with `set_sensitive`.
534     /// let mut auth_value = header::HeaderValue::from_static("secret");
535     /// auth_value.set_sensitive(true);
536     /// headers.insert(header::AUTHORIZATION, auth_value);
537     ///
538     /// // get a client builder
539     /// let client = reqwest::Client::builder()
540     ///     .default_headers(headers)
541     ///     .build()?;
542     /// let res = client.get("https://www.rust-lang.org").send().await?;
543     /// # Ok(())
544     /// # }
545     /// ```
546     ///
547     /// Override the default headers:
548     ///
549     /// ```rust
550     /// use reqwest::header;
551     /// # async fn doc() -> Result<(), reqwest::Error> {
552     /// let mut headers = header::HeaderMap::new();
553     /// headers.insert("X-MY-HEADER", header::HeaderValue::from_static("value"));
554     ///
555     /// // get a client builder
556     /// let client = reqwest::Client::builder()
557     ///     .default_headers(headers)
558     ///     .build()?;
559     /// let res = client
560     ///     .get("https://www.rust-lang.org")
561     ///     .header("X-MY-HEADER", "new_value")
562     ///     .send()
563     ///     .await?;
564     /// # Ok(())
565     /// # }
566     /// ```
default_headers(mut self, headers: HeaderMap) -> ClientBuilder567     pub fn default_headers(mut self, headers: HeaderMap) -> ClientBuilder {
568         for (key, value) in headers.iter() {
569             self.config.headers.insert(key, value.clone());
570         }
571         self
572     }
573 
574     /// Enable a persistent cookie store for the client.
575     ///
576     /// Cookies received in responses will be preserved and included in
577     /// additional requests.
578     ///
579     /// By default, no cookie store is used.
580     ///
581     /// # Optional
582     ///
583     /// This requires the optional `cookies` feature to be enabled.
584     #[cfg(feature = "cookies")]
585     #[cfg_attr(docsrs, doc(cfg(feature = "cookies")))]
cookie_store(mut self, enable: bool) -> ClientBuilder586     pub fn cookie_store(mut self, enable: bool) -> ClientBuilder {
587         if enable {
588             self.cookie_provider(Arc::new(cookie::Jar::default()))
589         } else {
590             self.config.cookie_store = None;
591             self
592         }
593     }
594 
595     /// Set the persistent cookie store for the client.
596     ///
597     /// Cookies received in responses will be passed to this store, and
598     /// additional requests will query this store for cookies.
599     ///
600     /// By default, no cookie store is used.
601     ///
602     /// # Optional
603     ///
604     /// This requires the optional `cookies` feature to be enabled.
605     #[cfg(feature = "cookies")]
606     #[cfg_attr(docsrs, doc(cfg(feature = "cookies")))]
cookie_provider<C: cookie::CookieStore + 'static>( mut self, cookie_store: Arc<C>, ) -> ClientBuilder607     pub fn cookie_provider<C: cookie::CookieStore + 'static>(
608         mut self,
609         cookie_store: Arc<C>,
610     ) -> ClientBuilder {
611         self.config.cookie_store = Some(cookie_store as _);
612         self
613     }
614 
615     /// Enable auto gzip decompression by checking the `Content-Encoding` response header.
616     ///
617     /// If auto gzip decompression is turned on:
618     ///
619     /// - When sending a request and if the request's headers do not already contain
620     ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `gzip`.
621     ///   The request body is **not** automatically compressed.
622     /// - When receiving a response, if its headers contain a `Content-Encoding` value of
623     ///   `gzip`, both `Content-Encoding` and `Content-Length` are removed from the
624     ///   headers' set. The response body is automatically decompressed.
625     ///
626     /// If the `gzip` feature is turned on, the default option is enabled.
627     ///
628     /// # Optional
629     ///
630     /// This requires the optional `gzip` feature to be enabled
631     #[cfg(feature = "gzip")]
632     #[cfg_attr(docsrs, doc(cfg(feature = "gzip")))]
gzip(mut self, enable: bool) -> ClientBuilder633     pub fn gzip(mut self, enable: bool) -> ClientBuilder {
634         self.config.accepts.gzip = enable;
635         self
636     }
637 
638     /// Enable auto brotli decompression by checking the `Content-Encoding` response header.
639     ///
640     /// If auto brotli decompression is turned on:
641     ///
642     /// - When sending a request and if the request's headers do not already contain
643     ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `br`.
644     ///   The request body is **not** automatically compressed.
645     /// - When receiving a response, if its headers contain a `Content-Encoding` value of
646     ///   `br`, both `Content-Encoding` and `Content-Length` are removed from the
647     ///   headers' set. The response body is automatically decompressed.
648     ///
649     /// If the `brotli` feature is turned on, the default option is enabled.
650     ///
651     /// # Optional
652     ///
653     /// This requires the optional `brotli` feature to be enabled
654     #[cfg(feature = "brotli")]
655     #[cfg_attr(docsrs, doc(cfg(feature = "brotli")))]
brotli(mut self, enable: bool) -> ClientBuilder656     pub fn brotli(mut self, enable: bool) -> ClientBuilder {
657         self.config.accepts.brotli = enable;
658         self
659     }
660 
661     /// Enable auto deflate decompression by checking the `Content-Encoding` response header.
662     ///
663     /// If auto deflate decompression is turned on:
664     ///
665     /// - When sending a request and if the request's headers do not already contain
666     ///   an `Accept-Encoding` **and** `Range` values, the `Accept-Encoding` header is set to `deflate`.
667     ///   The request body is **not** automatically compressed.
668     /// - When receiving a response, if it's headers contain a `Content-Encoding` value that
669     ///   equals to `deflate`, both values `Content-Encoding` and `Content-Length` are removed from the
670     ///   headers' set. The response body is automatically decompressed.
671     ///
672     /// If the `deflate` feature is turned on, the default option is enabled.
673     ///
674     /// # Optional
675     ///
676     /// This requires the optional `deflate` feature to be enabled
677     #[cfg(feature = "deflate")]
678     #[cfg_attr(docsrs, doc(cfg(feature = "deflate")))]
deflate(mut self, enable: bool) -> ClientBuilder679     pub fn deflate(mut self, enable: bool) -> ClientBuilder {
680         self.config.accepts.deflate = enable;
681         self
682     }
683 
684     /// Disable auto response body gzip decompression.
685     ///
686     /// This method exists even if the optional `gzip` feature is not enabled.
687     /// This can be used to ensure a `Client` doesn't use gzip decompression
688     /// even if another dependency were to enable the optional `gzip` feature.
no_gzip(self) -> ClientBuilder689     pub fn no_gzip(self) -> ClientBuilder {
690         #[cfg(feature = "gzip")]
691         {
692             self.gzip(false)
693         }
694 
695         #[cfg(not(feature = "gzip"))]
696         {
697             self
698         }
699     }
700 
701     /// Disable auto response body brotli decompression.
702     ///
703     /// This method exists even if the optional `brotli` feature is not enabled.
704     /// This can be used to ensure a `Client` doesn't use brotli decompression
705     /// even if another dependency were to enable the optional `brotli` feature.
no_brotli(self) -> ClientBuilder706     pub fn no_brotli(self) -> ClientBuilder {
707         #[cfg(feature = "brotli")]
708         {
709             self.brotli(false)
710         }
711 
712         #[cfg(not(feature = "brotli"))]
713         {
714             self
715         }
716     }
717 
718     /// Disable auto response body deflate decompression.
719     ///
720     /// This method exists even if the optional `deflate` feature is not enabled.
721     /// This can be used to ensure a `Client` doesn't use deflate decompression
722     /// even if another dependency were to enable the optional `deflate` feature.
no_deflate(self) -> ClientBuilder723     pub fn no_deflate(self) -> ClientBuilder {
724         #[cfg(feature = "deflate")]
725         {
726             self.deflate(false)
727         }
728 
729         #[cfg(not(feature = "deflate"))]
730         {
731             self
732         }
733     }
734 
735     // Redirect options
736 
737     /// Set a `RedirectPolicy` for this client.
738     ///
739     /// Default will follow redirects up to a maximum of 10.
redirect(mut self, policy: redirect::Policy) -> ClientBuilder740     pub fn redirect(mut self, policy: redirect::Policy) -> ClientBuilder {
741         self.config.redirect_policy = policy;
742         self
743     }
744 
745     /// Enable or disable automatic setting of the `Referer` header.
746     ///
747     /// Default is `true`.
referer(mut self, enable: bool) -> ClientBuilder748     pub fn referer(mut self, enable: bool) -> ClientBuilder {
749         self.config.referer = enable;
750         self
751     }
752 
753     // Proxy options
754 
755     /// Add a `Proxy` to the list of proxies the `Client` will use.
756     ///
757     /// # Note
758     ///
759     /// Adding a proxy will disable the automatic usage of the "system" proxy.
proxy(mut self, proxy: Proxy) -> ClientBuilder760     pub fn proxy(mut self, proxy: Proxy) -> ClientBuilder {
761         self.config.proxies.push(proxy);
762         self.config.auto_sys_proxy = false;
763         self
764     }
765 
766     /// Clear all `Proxies`, so `Client` will use no proxy anymore.
767     ///
768     /// This also disables the automatic usage of the "system" proxy.
no_proxy(mut self) -> ClientBuilder769     pub fn no_proxy(mut self) -> ClientBuilder {
770         self.config.proxies.clear();
771         self.config.auto_sys_proxy = false;
772         self
773     }
774 
775     // Timeout options
776 
777     /// Enables a request timeout.
778     ///
779     /// The timeout is applied from when the request starts connecting until the
780     /// response body has finished.
781     ///
782     /// Default is no timeout.
timeout(mut self, timeout: Duration) -> ClientBuilder783     pub fn timeout(mut self, timeout: Duration) -> ClientBuilder {
784         self.config.timeout = Some(timeout);
785         self
786     }
787 
788     /// Set a timeout for only the connect phase of a `Client`.
789     ///
790     /// Default is `None`.
791     ///
792     /// # Note
793     ///
794     /// This **requires** the futures be executed in a tokio runtime with
795     /// a tokio timer enabled.
connect_timeout(mut self, timeout: Duration) -> ClientBuilder796     pub fn connect_timeout(mut self, timeout: Duration) -> ClientBuilder {
797         self.config.connect_timeout = Some(timeout);
798         self
799     }
800 
801     /// Set whether connections should emit verbose logs.
802     ///
803     /// Enabling this option will emit [log][] messages at the `TRACE` level
804     /// for read and write operations on connections.
805     ///
806     /// [log]: https://crates.io/crates/log
connection_verbose(mut self, verbose: bool) -> ClientBuilder807     pub fn connection_verbose(mut self, verbose: bool) -> ClientBuilder {
808         self.config.connection_verbose = verbose;
809         self
810     }
811 
812     // HTTP options
813 
814     /// Set an optional timeout for idle sockets being kept-alive.
815     ///
816     /// Pass `None` to disable timeout.
817     ///
818     /// Default is 90 seconds.
pool_idle_timeout<D>(mut self, val: D) -> ClientBuilder where D: Into<Option<Duration>>,819     pub fn pool_idle_timeout<D>(mut self, val: D) -> ClientBuilder
820     where
821         D: Into<Option<Duration>>,
822     {
823         self.config.pool_idle_timeout = val.into();
824         self
825     }
826 
827     /// Sets the maximum idle connection per host allowed in the pool.
pool_max_idle_per_host(mut self, max: usize) -> ClientBuilder828     pub fn pool_max_idle_per_host(mut self, max: usize) -> ClientBuilder {
829         self.config.pool_max_idle_per_host = max;
830         self
831     }
832 
833     /// Send headers as title case instead of lowercase.
http1_title_case_headers(mut self) -> ClientBuilder834     pub fn http1_title_case_headers(mut self) -> ClientBuilder {
835         self.config.http1_title_case_headers = true;
836         self
837     }
838 
839     /// Only use HTTP/1.
http1_only(mut self) -> ClientBuilder840     pub fn http1_only(mut self) -> ClientBuilder {
841         self.config.http_version_pref = HttpVersionPref::Http1;
842         self
843     }
844 
845     /// Only use HTTP/2.
http2_prior_knowledge(mut self) -> ClientBuilder846     pub fn http2_prior_knowledge(mut self) -> ClientBuilder {
847         self.config.http_version_pref = HttpVersionPref::Http2;
848         self
849     }
850 
851     /// Sets the `SETTINGS_INITIAL_WINDOW_SIZE` option for HTTP2 stream-level flow control.
852     ///
853     /// Default is currently 65,535 but may change internally to optimize for common uses.
http2_initial_stream_window_size(mut self, sz: impl Into<Option<u32>>) -> ClientBuilder854     pub fn http2_initial_stream_window_size(mut self, sz: impl Into<Option<u32>>) -> ClientBuilder {
855         self.config.http2_initial_stream_window_size = sz.into();
856         self
857     }
858 
859     /// Sets the max connection-level flow control for HTTP2
860     ///
861     /// Default is currently 65,535 but may change internally to optimize for common uses.
http2_initial_connection_window_size( mut self, sz: impl Into<Option<u32>>, ) -> ClientBuilder862     pub fn http2_initial_connection_window_size(
863         mut self,
864         sz: impl Into<Option<u32>>,
865     ) -> ClientBuilder {
866         self.config.http2_initial_connection_window_size = sz.into();
867         self
868     }
869 
870     /// Sets whether to use an adaptive flow control.
871     ///
872     /// Enabling this will override the limits set in `http2_initial_stream_window_size` and
873     /// `http2_initial_connection_window_size`.
http2_adaptive_window(mut self, enabled: bool) -> ClientBuilder874     pub fn http2_adaptive_window(mut self, enabled: bool) -> ClientBuilder {
875         self.config.http2_adaptive_window = enabled;
876         self
877     }
878 
879     /// Sets the maximum frame size to use for HTTP2.
880     ///
881     /// Default is currently 16,384 but may change internally to optimize for common uses.
http2_max_frame_size(mut self, sz: impl Into<Option<u32>>) -> ClientBuilder882     pub fn http2_max_frame_size(mut self, sz: impl Into<Option<u32>>) -> ClientBuilder {
883         self.config.http2_max_frame_size = sz.into();
884         self
885     }
886 
887     // TCP options
888 
889     /// Set whether sockets have `SO_NODELAY` enabled.
890     ///
891     /// Default is `true`.
tcp_nodelay(mut self, enabled: bool) -> ClientBuilder892     pub fn tcp_nodelay(mut self, enabled: bool) -> ClientBuilder {
893         self.config.nodelay = enabled;
894         self
895     }
896 
897     /// Bind to a local IP Address.
898     ///
899     /// # Example
900     ///
901     /// ```
902     /// use std::net::IpAddr;
903     /// let local_addr = IpAddr::from([12, 4, 1, 8]);
904     /// let client = reqwest::Client::builder()
905     ///     .local_address(local_addr)
906     ///     .build().unwrap();
907     /// ```
local_address<T>(mut self, addr: T) -> ClientBuilder where T: Into<Option<IpAddr>>,908     pub fn local_address<T>(mut self, addr: T) -> ClientBuilder
909     where
910         T: Into<Option<IpAddr>>,
911     {
912         self.config.local_address = addr.into();
913         self
914     }
915 
916     /// Set that all sockets have `SO_KEEPALIVE` set with the supplied duration.
917     ///
918     /// If `None`, the option will not be set.
tcp_keepalive<D>(mut self, val: D) -> ClientBuilder where D: Into<Option<Duration>>,919     pub fn tcp_keepalive<D>(mut self, val: D) -> ClientBuilder
920     where
921         D: Into<Option<Duration>>,
922     {
923         self.config.tcp_keepalive = val.into();
924         self
925     }
926 
927     // TLS options
928 
929     /// Add a custom root certificate.
930     ///
931     /// This can be used to connect to a server that has a self-signed
932     /// certificate for example.
933     ///
934     /// # Optional
935     ///
936     /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
937     /// feature to be enabled.
938     #[cfg(feature = "__tls")]
939     #[cfg_attr(
940         docsrs,
941         doc(cfg(any(
942             feature = "default-tls",
943             feature = "native-tls",
944             feature = "rustls-tls"
945         )))
946     )]
add_root_certificate(mut self, cert: Certificate) -> ClientBuilder947     pub fn add_root_certificate(mut self, cert: Certificate) -> ClientBuilder {
948         self.config.root_certs.push(cert);
949         self
950     }
951 
952     /// Controls the use of built-in/preloaded certificates during certificate validation.
953     ///
954     /// Defaults to `true` -- built-in system certs will be used.
955     ///
956     /// # Optional
957     ///
958     /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
959     /// feature to be enabled.
960     #[cfg(feature = "__tls")]
961     #[cfg_attr(
962         docsrs,
963         doc(cfg(any(
964             feature = "default-tls",
965             feature = "native-tls",
966             feature = "rustls-tls"
967         )))
968     )]
tls_built_in_root_certs(mut self, tls_built_in_root_certs: bool) -> ClientBuilder969     pub fn tls_built_in_root_certs(mut self, tls_built_in_root_certs: bool) -> ClientBuilder {
970         self.config.tls_built_in_root_certs = tls_built_in_root_certs;
971         self
972     }
973 
974     /// Sets the identity to be used for client certificate authentication.
975     ///
976     /// # Optional
977     ///
978     /// This requires the optional `native-tls` or `rustls-tls(-...)` feature to be
979     /// enabled.
980     #[cfg(any(feature = "native-tls", feature = "__rustls"))]
981     #[cfg_attr(docsrs, doc(cfg(any(feature = "native-tls", feature = "rustls-tls"))))]
identity(mut self, identity: Identity) -> ClientBuilder982     pub fn identity(mut self, identity: Identity) -> ClientBuilder {
983         self.config.identity = Some(identity);
984         self
985     }
986 
987     /// Controls the use of hostname verification.
988     ///
989     /// Defaults to `false`.
990     ///
991     /// # Warning
992     ///
993     /// You should think very carefully before you use this method. If
994     /// hostname verification is not used, any valid certificate for any
995     /// site will be trusted for use from any other. This introduces a
996     /// significant vulnerability to man-in-the-middle attacks.
997     ///
998     /// # Optional
999     ///
1000     /// This requires the optional `native-tls` feature to be enabled.
1001     #[cfg(feature = "native-tls")]
1002     #[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))]
danger_accept_invalid_hostnames( mut self, accept_invalid_hostname: bool, ) -> ClientBuilder1003     pub fn danger_accept_invalid_hostnames(
1004         mut self,
1005         accept_invalid_hostname: bool,
1006     ) -> ClientBuilder {
1007         self.config.hostname_verification = !accept_invalid_hostname;
1008         self
1009     }
1010 
1011     /// Controls the use of certificate validation.
1012     ///
1013     /// Defaults to `false`.
1014     ///
1015     /// # Warning
1016     ///
1017     /// You should think very carefully before using this method. If
1018     /// invalid certificates are trusted, *any* certificate for *any* site
1019     /// will be trusted for use. This includes expired certificates. This
1020     /// introduces significant vulnerabilities, and should only be used
1021     /// as a last resort.
1022     ///
1023     /// # Optional
1024     ///
1025     /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
1026     /// feature to be enabled.
1027     #[cfg(feature = "__tls")]
1028     #[cfg_attr(
1029         docsrs,
1030         doc(cfg(any(
1031             feature = "default-tls",
1032             feature = "native-tls",
1033             feature = "rustls-tls"
1034         )))
1035     )]
danger_accept_invalid_certs(mut self, accept_invalid_certs: bool) -> ClientBuilder1036     pub fn danger_accept_invalid_certs(mut self, accept_invalid_certs: bool) -> ClientBuilder {
1037         self.config.certs_verification = !accept_invalid_certs;
1038         self
1039     }
1040 
1041     /// Set the minimum required TLS version for connections.
1042     ///
1043     /// By default the TLS backend's own default is used.
1044     ///
1045     /// # Errors
1046     ///
1047     /// A value of `tls::Version::TLS_1_3` will cause an error with the
1048     /// `native-tls`/`default-tls` backend. This does not mean the version
1049     /// isn't supported, just that it can't be set as a minimum due to
1050     /// technical limitations.
1051     ///
1052     /// # Optional
1053     ///
1054     /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
1055     /// feature to be enabled.
1056     #[cfg(feature = "__tls")]
1057     #[cfg_attr(
1058         docsrs,
1059         doc(cfg(any(
1060             feature = "default-tls",
1061             feature = "native-tls",
1062             feature = "rustls-tls"
1063         )))
1064     )]
min_tls_version(mut self, version: tls::Version) -> ClientBuilder1065     pub fn min_tls_version(mut self, version: tls::Version) -> ClientBuilder {
1066         self.config.min_tls_version = Some(version);
1067         self
1068     }
1069 
1070     /// Set the maximum allowed TLS version for connections.
1071     ///
1072     /// By default there's no maximum.
1073     ///
1074     /// # Errors
1075     ///
1076     /// A value of `tls::Version::TLS_1_3` will cause an error with the
1077     /// `native-tls`/`default-tls` backend. This does not mean the version
1078     /// isn't supported, just that it can't be set as a maximum due to
1079     /// technical limitations.
1080     ///
1081     /// # Optional
1082     ///
1083     /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
1084     /// feature to be enabled.
1085     #[cfg(feature = "__tls")]
1086     #[cfg_attr(
1087         docsrs,
1088         doc(cfg(any(
1089             feature = "default-tls",
1090             feature = "native-tls",
1091             feature = "rustls-tls"
1092         )))
1093     )]
max_tls_version(mut self, version: tls::Version) -> ClientBuilder1094     pub fn max_tls_version(mut self, version: tls::Version) -> ClientBuilder {
1095         self.config.max_tls_version = Some(version);
1096         self
1097     }
1098 
1099     /// Force using the native TLS backend.
1100     ///
1101     /// Since multiple TLS backends can be optionally enabled, this option will
1102     /// force the `native-tls` backend to be used for this `Client`.
1103     ///
1104     /// # Optional
1105     ///
1106     /// This requires the optional `native-tls` feature to be enabled.
1107     #[cfg(feature = "native-tls")]
1108     #[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))]
use_native_tls(mut self) -> ClientBuilder1109     pub fn use_native_tls(mut self) -> ClientBuilder {
1110         self.config.tls = TlsBackend::Default;
1111         self
1112     }
1113 
1114     /// Force using the Rustls TLS backend.
1115     ///
1116     /// Since multiple TLS backends can be optionally enabled, this option will
1117     /// force the `rustls` backend to be used for this `Client`.
1118     ///
1119     /// # Optional
1120     ///
1121     /// This requires the optional `rustls-tls(-...)` feature to be enabled.
1122     #[cfg(feature = "__rustls")]
1123     #[cfg_attr(docsrs, doc(cfg(feature = "rustls-tls")))]
use_rustls_tls(mut self) -> ClientBuilder1124     pub fn use_rustls_tls(mut self) -> ClientBuilder {
1125         self.config.tls = TlsBackend::Rustls;
1126         self
1127     }
1128 
1129     /// Use a preconfigured TLS backend.
1130     ///
1131     /// If the passed `Any` argument is not a TLS backend that reqwest
1132     /// understands, the `ClientBuilder` will error when calling `build`.
1133     ///
1134     /// # Advanced
1135     ///
1136     /// This is an advanced option, and can be somewhat brittle. Usage requires
1137     /// keeping the preconfigured TLS argument version in sync with reqwest,
1138     /// since version mismatches will result in an "unknown" TLS backend.
1139     ///
1140     /// If possible, it's preferable to use the methods on `ClientBuilder`
1141     /// to configure reqwest's TLS.
1142     ///
1143     /// # Optional
1144     ///
1145     /// This requires one of the optional features `native-tls` or
1146     /// `rustls-tls(-...)` to be enabled.
1147     #[cfg(any(feature = "native-tls", feature = "__rustls",))]
1148     #[cfg_attr(docsrs, doc(cfg(any(feature = "native-tls", feature = "rustls-tls"))))]
use_preconfigured_tls(mut self, tls: impl Any) -> ClientBuilder1149     pub fn use_preconfigured_tls(mut self, tls: impl Any) -> ClientBuilder {
1150         let mut tls = Some(tls);
1151         #[cfg(feature = "native-tls")]
1152         {
1153             if let Some(conn) =
1154                 (&mut tls as &mut dyn Any).downcast_mut::<Option<native_tls_crate::TlsConnector>>()
1155             {
1156                 let tls = conn.take().expect("is definitely Some");
1157                 let tls = crate::tls::TlsBackend::BuiltNativeTls(tls);
1158                 self.config.tls = tls;
1159                 return self;
1160             }
1161         }
1162         #[cfg(feature = "__rustls")]
1163         {
1164             if let Some(conn) =
1165                 (&mut tls as &mut dyn Any).downcast_mut::<Option<rustls::ClientConfig>>()
1166             {
1167                 let tls = conn.take().expect("is definitely Some");
1168                 let tls = crate::tls::TlsBackend::BuiltRustls(tls);
1169                 self.config.tls = tls;
1170                 return self;
1171             }
1172         }
1173 
1174         // Otherwise, we don't recognize the TLS backend!
1175         self.config.tls = crate::tls::TlsBackend::UnknownPreconfigured;
1176         self
1177     }
1178 
1179     /// Enables the [trust-dns](trust_dns_resolver) async resolver instead of a default threadpool using `getaddrinfo`.
1180     ///
1181     /// If the `trust-dns` feature is turned on, the default option is enabled.
1182     ///
1183     /// # Optional
1184     ///
1185     /// This requires the optional `trust-dns` feature to be enabled
1186     #[cfg(feature = "trust-dns")]
1187     #[cfg_attr(docsrs, doc(cfg(feature = "trust-dns")))]
trust_dns(mut self, enable: bool) -> ClientBuilder1188     pub fn trust_dns(mut self, enable: bool) -> ClientBuilder {
1189         self.config.trust_dns = enable;
1190         self
1191     }
1192 
1193     /// Disables the trust-dns async resolver.
1194     ///
1195     /// This method exists even if the optional `trust-dns` feature is not enabled.
1196     /// This can be used to ensure a `Client` doesn't use the trust-dns async resolver
1197     /// even if another dependency were to enable the optional `trust-dns` feature.
no_trust_dns(self) -> ClientBuilder1198     pub fn no_trust_dns(self) -> ClientBuilder {
1199         #[cfg(feature = "trust-dns")]
1200         {
1201             self.trust_dns(false)
1202         }
1203 
1204         #[cfg(not(feature = "trust-dns"))]
1205         {
1206             self
1207         }
1208     }
1209 
1210     /// Restrict the Client to be used with HTTPS only requests.
1211     ///
1212     /// Defaults to false.
https_only(mut self, enabled: bool) -> ClientBuilder1213     pub fn https_only(mut self, enabled: bool) -> ClientBuilder {
1214         self.config.https_only = enabled;
1215         self
1216     }
1217 
1218     /// Override DNS resolution for specific domains to particular IP addresses.
1219     ///
1220     /// Warning
1221     ///
1222     /// Since the DNS protocol has no notion of ports, if you wish to send
1223     /// traffic to a particular port you must include this port in the URL
1224     /// itself, any port in the overridden addr will be ignored and traffic sent
1225     /// to the conventional port for the given scheme (e.g. 80 for http).
resolve(mut self, domain: &str, addr: SocketAddr) -> ClientBuilder1226     pub fn resolve(mut self, domain: &str, addr: SocketAddr) -> ClientBuilder {
1227         self.config.dns_overrides.insert(domain.to_string(), addr);
1228         self
1229     }
1230 }
1231 
1232 type HyperClient = hyper::Client<Connector, super::body::ImplStream>;
1233 
1234 impl Default for Client {
default() -> Self1235     fn default() -> Self {
1236         Self::new()
1237     }
1238 }
1239 
1240 impl Client {
1241     /// Constructs a new `Client`.
1242     ///
1243     /// # Panics
1244     ///
1245     /// This method panics if a TLS backend cannot initialized, or the resolver
1246     /// cannot load the system configuration.
1247     ///
1248     /// Use `Client::builder()` if you wish to handle the failure as an `Error`
1249     /// instead of panicking.
new() -> Client1250     pub fn new() -> Client {
1251         ClientBuilder::new().build().expect("Client::new()")
1252     }
1253 
1254     /// Creates a `ClientBuilder` to configure a `Client`.
1255     ///
1256     /// This is the same as `ClientBuilder::new()`.
builder() -> ClientBuilder1257     pub fn builder() -> ClientBuilder {
1258         ClientBuilder::new()
1259     }
1260 
1261     /// Convenience method to make a `GET` request to a URL.
1262     ///
1263     /// # Errors
1264     ///
1265     /// This method fails whenever the supplied `Url` cannot be parsed.
get<U: IntoUrl>(&self, url: U) -> RequestBuilder1266     pub fn get<U: IntoUrl>(&self, url: U) -> RequestBuilder {
1267         self.request(Method::GET, url)
1268     }
1269 
1270     /// Convenience method to make a `POST` request to a URL.
1271     ///
1272     /// # Errors
1273     ///
1274     /// This method fails whenever the supplied `Url` cannot be parsed.
post<U: IntoUrl>(&self, url: U) -> RequestBuilder1275     pub fn post<U: IntoUrl>(&self, url: U) -> RequestBuilder {
1276         self.request(Method::POST, url)
1277     }
1278 
1279     /// Convenience method to make a `PUT` request to a URL.
1280     ///
1281     /// # Errors
1282     ///
1283     /// This method fails whenever the supplied `Url` cannot be parsed.
put<U: IntoUrl>(&self, url: U) -> RequestBuilder1284     pub fn put<U: IntoUrl>(&self, url: U) -> RequestBuilder {
1285         self.request(Method::PUT, url)
1286     }
1287 
1288     /// Convenience method to make a `PATCH` request to a URL.
1289     ///
1290     /// # Errors
1291     ///
1292     /// This method fails whenever the supplied `Url` cannot be parsed.
patch<U: IntoUrl>(&self, url: U) -> RequestBuilder1293     pub fn patch<U: IntoUrl>(&self, url: U) -> RequestBuilder {
1294         self.request(Method::PATCH, url)
1295     }
1296 
1297     /// Convenience method to make a `DELETE` request to a URL.
1298     ///
1299     /// # Errors
1300     ///
1301     /// This method fails whenever the supplied `Url` cannot be parsed.
delete<U: IntoUrl>(&self, url: U) -> RequestBuilder1302     pub fn delete<U: IntoUrl>(&self, url: U) -> RequestBuilder {
1303         self.request(Method::DELETE, url)
1304     }
1305 
1306     /// Convenience method to make a `HEAD` request to a URL.
1307     ///
1308     /// # Errors
1309     ///
1310     /// This method fails whenever the supplied `Url` cannot be parsed.
head<U: IntoUrl>(&self, url: U) -> RequestBuilder1311     pub fn head<U: IntoUrl>(&self, url: U) -> RequestBuilder {
1312         self.request(Method::HEAD, url)
1313     }
1314 
1315     /// Start building a `Request` with the `Method` and `Url`.
1316     ///
1317     /// Returns a `RequestBuilder`, which will allow setting headers and
1318     /// the request body before sending.
1319     ///
1320     /// # Errors
1321     ///
1322     /// This method fails whenever the supplied `Url` cannot be parsed.
request<U: IntoUrl>(&self, method: Method, url: U) -> RequestBuilder1323     pub fn request<U: IntoUrl>(&self, method: Method, url: U) -> RequestBuilder {
1324         let req = url.into_url().map(move |url| Request::new(method, url));
1325         RequestBuilder::new(self.clone(), req)
1326     }
1327 
1328     /// Executes a `Request`.
1329     ///
1330     /// A `Request` can be built manually with `Request::new()` or obtained
1331     /// from a RequestBuilder with `RequestBuilder::build()`.
1332     ///
1333     /// You should prefer to use the `RequestBuilder` and
1334     /// `RequestBuilder::send()`.
1335     ///
1336     /// # Errors
1337     ///
1338     /// This method fails if there was an error while sending request,
1339     /// redirect loop was detected or redirect limit was exhausted.
execute( &self, request: Request, ) -> impl Future<Output = Result<Response, crate::Error>>1340     pub fn execute(
1341         &self,
1342         request: Request,
1343     ) -> impl Future<Output = Result<Response, crate::Error>> {
1344         self.execute_request(request)
1345     }
1346 
execute_request(&self, req: Request) -> Pending1347     pub(super) fn execute_request(&self, req: Request) -> Pending {
1348         let (method, url, mut headers, body, timeout, version) = req.pieces();
1349         if url.scheme() != "http" && url.scheme() != "https" {
1350             return Pending::new_err(error::url_bad_scheme(url));
1351         }
1352 
1353         // check if we're in https_only mode and check the scheme of the current URL
1354         if self.inner.https_only && url.scheme() != "https" {
1355             return Pending::new_err(error::url_bad_scheme(url));
1356         }
1357 
1358         // insert default headers in the request headers
1359         // without overwriting already appended headers.
1360         for (key, value) in &self.inner.headers {
1361             if let Entry::Vacant(entry) = headers.entry(key) {
1362                 entry.insert(value.clone());
1363             }
1364         }
1365 
1366         // Add cookies from the cookie store.
1367         #[cfg(feature = "cookies")]
1368         {
1369             if let Some(cookie_store) = self.inner.cookie_store.as_ref() {
1370                 if headers.get(crate::header::COOKIE).is_none() {
1371                     add_cookie_header(&mut headers, &**cookie_store, &url);
1372                 }
1373             }
1374         }
1375 
1376         let accept_encoding = self.inner.accepts.as_str();
1377 
1378         if let Some(accept_encoding) = accept_encoding {
1379             if !headers.contains_key(ACCEPT_ENCODING) && !headers.contains_key(RANGE) {
1380                 headers.insert(ACCEPT_ENCODING, HeaderValue::from_static(accept_encoding));
1381             }
1382         }
1383 
1384         let uri = expect_uri(&url);
1385 
1386         let (reusable, body) = match body {
1387             Some(body) => {
1388                 let (reusable, body) = body.try_reuse();
1389                 (Some(reusable), body)
1390             }
1391             None => (None, Body::empty()),
1392         };
1393 
1394         self.proxy_auth(&uri, &mut headers);
1395 
1396         let mut req = hyper::Request::builder()
1397             .method(method.clone())
1398             .uri(uri)
1399             .version(version)
1400             .body(body.into_stream())
1401             .expect("valid request parts");
1402 
1403         let timeout = timeout
1404             .or(self.inner.request_timeout)
1405             .map(tokio::time::sleep)
1406             .map(Box::pin);
1407 
1408         *req.headers_mut() = headers.clone();
1409 
1410         let in_flight = self.inner.hyper.request(req);
1411 
1412         Pending {
1413             inner: PendingInner::Request(PendingRequest {
1414                 method,
1415                 url,
1416                 headers,
1417                 body: reusable,
1418 
1419                 urls: Vec::new(),
1420 
1421                 client: self.inner.clone(),
1422 
1423                 in_flight,
1424                 timeout,
1425             }),
1426         }
1427     }
1428 
proxy_auth(&self, dst: &Uri, headers: &mut HeaderMap)1429     fn proxy_auth(&self, dst: &Uri, headers: &mut HeaderMap) {
1430         if !self.inner.proxies_maybe_http_auth {
1431             return;
1432         }
1433 
1434         // Only set the header here if the destination scheme is 'http',
1435         // since otherwise, the header will be included in the CONNECT tunnel
1436         // request instead.
1437         if dst.scheme() != Some(&Scheme::HTTP) {
1438             return;
1439         }
1440 
1441         if headers.contains_key(PROXY_AUTHORIZATION) {
1442             return;
1443         }
1444 
1445         for proxy in self.inner.proxies.iter() {
1446             if proxy.is_match(dst) {
1447                 if let Some(header) = proxy.http_basic_auth(dst) {
1448                     headers.insert(PROXY_AUTHORIZATION, header);
1449                 }
1450 
1451                 break;
1452             }
1453         }
1454     }
1455 }
1456 
1457 impl fmt::Debug for Client {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1458     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1459         let mut builder = f.debug_struct("Client");
1460         self.inner.fmt_fields(&mut builder);
1461         builder.finish()
1462     }
1463 }
1464 
1465 impl fmt::Debug for ClientBuilder {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1466     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1467         let mut builder = f.debug_struct("ClientBuilder");
1468         self.config.fmt_fields(&mut builder);
1469         builder.finish()
1470     }
1471 }
1472 
1473 impl Config {
fmt_fields(&self, f: &mut fmt::DebugStruct<'_, '_>)1474     fn fmt_fields(&self, f: &mut fmt::DebugStruct<'_, '_>) {
1475         // Instead of deriving Debug, only print fields when their output
1476         // would provide relevant or interesting data.
1477 
1478         #[cfg(feature = "cookies")]
1479         {
1480             if let Some(_) = self.cookie_store {
1481                 f.field("cookie_store", &true);
1482             }
1483         }
1484 
1485         f.field("accepts", &self.accepts);
1486 
1487         if !self.proxies.is_empty() {
1488             f.field("proxies", &self.proxies);
1489         }
1490 
1491         if !self.redirect_policy.is_default() {
1492             f.field("redirect_policy", &self.redirect_policy);
1493         }
1494 
1495         if self.referer {
1496             f.field("referer", &true);
1497         }
1498 
1499         f.field("default_headers", &self.headers);
1500 
1501         if self.http1_title_case_headers {
1502             f.field("http1_title_case_headers", &true);
1503         }
1504 
1505         if matches!(self.http_version_pref, HttpVersionPref::Http1) {
1506             f.field("http1_only", &true);
1507         }
1508 
1509         if matches!(self.http_version_pref, HttpVersionPref::Http2) {
1510             f.field("http2_prior_knowledge", &true);
1511         }
1512 
1513         if let Some(ref d) = self.connect_timeout {
1514             f.field("connect_timeout", d);
1515         }
1516 
1517         if let Some(ref d) = self.timeout {
1518             f.field("timeout", d);
1519         }
1520 
1521         if let Some(ref v) = self.local_address {
1522             f.field("local_address", v);
1523         }
1524 
1525         if self.nodelay {
1526             f.field("tcp_nodelay", &true);
1527         }
1528 
1529         #[cfg(feature = "native-tls")]
1530         {
1531             if !self.hostname_verification {
1532                 f.field("danger_accept_invalid_hostnames", &true);
1533             }
1534         }
1535 
1536         #[cfg(feature = "__tls")]
1537         {
1538             if !self.certs_verification {
1539                 f.field("danger_accept_invalid_certs", &true);
1540             }
1541 
1542             if let Some(ref min_tls_version) = self.min_tls_version {
1543                 f.field("min_tls_version", min_tls_version);
1544             }
1545 
1546             if let Some(ref max_tls_version) = self.max_tls_version {
1547                 f.field("max_tls_version", max_tls_version);
1548             }
1549         }
1550 
1551         #[cfg(all(feature = "native-tls-crate", feature = "__rustls"))]
1552         {
1553             f.field("tls_backend", &self.tls);
1554         }
1555 
1556         if !self.dns_overrides.is_empty() {
1557             f.field("dns_overrides", &self.dns_overrides);
1558         }
1559     }
1560 }
1561 
1562 struct ClientRef {
1563     accepts: Accepts,
1564     #[cfg(feature = "cookies")]
1565     cookie_store: Option<Arc<dyn cookie::CookieStore>>,
1566     headers: HeaderMap,
1567     hyper: HyperClient,
1568     redirect_policy: redirect::Policy,
1569     referer: bool,
1570     request_timeout: Option<Duration>,
1571     proxies: Arc<Vec<Proxy>>,
1572     proxies_maybe_http_auth: bool,
1573     https_only: bool,
1574 }
1575 
1576 impl ClientRef {
fmt_fields(&self, f: &mut fmt::DebugStruct<'_, '_>)1577     fn fmt_fields(&self, f: &mut fmt::DebugStruct<'_, '_>) {
1578         // Instead of deriving Debug, only print fields when their output
1579         // would provide relevant or interesting data.
1580 
1581         #[cfg(feature = "cookies")]
1582         {
1583             if let Some(_) = self.cookie_store {
1584                 f.field("cookie_store", &true);
1585             }
1586         }
1587 
1588         f.field("accepts", &self.accepts);
1589 
1590         if !self.proxies.is_empty() {
1591             f.field("proxies", &self.proxies);
1592         }
1593 
1594         if !self.redirect_policy.is_default() {
1595             f.field("redirect_policy", &self.redirect_policy);
1596         }
1597 
1598         if self.referer {
1599             f.field("referer", &true);
1600         }
1601 
1602         f.field("default_headers", &self.headers);
1603 
1604         if let Some(ref d) = self.request_timeout {
1605             f.field("timeout", d);
1606         }
1607     }
1608 }
1609 
1610 pin_project! {
1611     pub(super) struct Pending {
1612         #[pin]
1613         inner: PendingInner,
1614     }
1615 }
1616 
1617 enum PendingInner {
1618     Request(PendingRequest),
1619     Error(Option<crate::Error>),
1620 }
1621 
1622 pin_project! {
1623     struct PendingRequest {
1624         method: Method,
1625         url: Url,
1626         headers: HeaderMap,
1627         body: Option<Option<Bytes>>,
1628 
1629         urls: Vec<Url>,
1630 
1631         client: Arc<ClientRef>,
1632 
1633         #[pin]
1634         in_flight: ResponseFuture,
1635         #[pin]
1636         timeout: Option<Pin<Box<Sleep>>>,
1637     }
1638 }
1639 
1640 impl PendingRequest {
in_flight(self: Pin<&mut Self>) -> Pin<&mut ResponseFuture>1641     fn in_flight(self: Pin<&mut Self>) -> Pin<&mut ResponseFuture> {
1642         self.project().in_flight
1643     }
1644 
timeout(self: Pin<&mut Self>) -> Pin<&mut Option<Pin<Box<Sleep>>>>1645     fn timeout(self: Pin<&mut Self>) -> Pin<&mut Option<Pin<Box<Sleep>>>> {
1646         self.project().timeout
1647     }
1648 
urls(self: Pin<&mut Self>) -> &mut Vec<Url>1649     fn urls(self: Pin<&mut Self>) -> &mut Vec<Url> {
1650         self.project().urls
1651     }
1652 
headers(self: Pin<&mut Self>) -> &mut HeaderMap1653     fn headers(self: Pin<&mut Self>) -> &mut HeaderMap {
1654         self.project().headers
1655     }
1656 }
1657 
1658 impl Pending {
new_err(err: crate::Error) -> Pending1659     pub(super) fn new_err(err: crate::Error) -> Pending {
1660         Pending {
1661             inner: PendingInner::Error(Some(err)),
1662         }
1663     }
1664 
inner(self: Pin<&mut Self>) -> Pin<&mut PendingInner>1665     fn inner(self: Pin<&mut Self>) -> Pin<&mut PendingInner> {
1666         self.project().inner
1667     }
1668 }
1669 
1670 impl Future for Pending {
1671     type Output = Result<Response, crate::Error>;
1672 
poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>1673     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1674         let inner = self.inner();
1675         match inner.get_mut() {
1676             PendingInner::Request(ref mut req) => Pin::new(req).poll(cx),
1677             PendingInner::Error(ref mut err) => Poll::Ready(Err(err
1678                 .take()
1679                 .expect("Pending error polled more than once"))),
1680         }
1681     }
1682 }
1683 
1684 impl Future for PendingRequest {
1685     type Output = Result<Response, crate::Error>;
1686 
poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>1687     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1688         if let Some(delay) = self.as_mut().timeout().as_mut().as_pin_mut() {
1689             if let Poll::Ready(()) = delay.poll(cx) {
1690                 return Poll::Ready(Err(
1691                     crate::error::request(crate::error::TimedOut).with_url(self.url.clone())
1692                 ));
1693             }
1694         }
1695 
1696         loop {
1697             let res = match self.as_mut().in_flight().as_mut().poll(cx) {
1698                 Poll::Ready(Err(e)) => {
1699                     return Poll::Ready(Err(crate::error::request(e).with_url(self.url.clone())));
1700                 }
1701                 Poll::Ready(Ok(res)) => res,
1702                 Poll::Pending => return Poll::Pending,
1703             };
1704 
1705             #[cfg(feature = "cookies")]
1706             {
1707                 if let Some(ref cookie_store) = self.client.cookie_store {
1708                     let mut cookies =
1709                         cookie::extract_response_cookie_headers(&res.headers()).peekable();
1710                     if cookies.peek().is_some() {
1711                         cookie_store.set_cookies(&mut cookies, &self.url);
1712                     }
1713                 }
1714             }
1715             let should_redirect = match res.status() {
1716                 StatusCode::MOVED_PERMANENTLY | StatusCode::FOUND | StatusCode::SEE_OTHER => {
1717                     self.body = None;
1718                     for header in &[
1719                         TRANSFER_ENCODING,
1720                         CONTENT_ENCODING,
1721                         CONTENT_TYPE,
1722                         CONTENT_LENGTH,
1723                     ] {
1724                         self.headers.remove(header);
1725                     }
1726 
1727                     match self.method {
1728                         Method::GET | Method::HEAD => {}
1729                         _ => {
1730                             self.method = Method::GET;
1731                         }
1732                     }
1733                     true
1734                 }
1735                 StatusCode::TEMPORARY_REDIRECT | StatusCode::PERMANENT_REDIRECT => {
1736                     match self.body {
1737                         Some(Some(_)) | None => true,
1738                         Some(None) => false,
1739                     }
1740                 }
1741                 _ => false,
1742             };
1743             if should_redirect {
1744                 let loc = res.headers().get(LOCATION).and_then(|val| {
1745                     let loc = (|| -> Option<Url> {
1746                         // Some sites may send a utf-8 Location header,
1747                         // even though we're supposed to treat those bytes
1748                         // as opaque, we'll check specifically for utf8.
1749                         self.url.join(str::from_utf8(val.as_bytes()).ok()?).ok()
1750                     })();
1751 
1752                     // Check that the `url` is also a valid `http::Uri`.
1753                     //
1754                     // If not, just log it and skip the redirect.
1755                     let loc = loc.and_then(|url| {
1756                         if try_uri(&url).is_some() {
1757                             Some(url)
1758                         } else {
1759                             None
1760                         }
1761                     });
1762 
1763                     if loc.is_none() {
1764                         debug!("Location header had invalid URI: {:?}", val);
1765                     }
1766                     loc
1767                 });
1768                 if let Some(loc) = loc {
1769                     if self.client.referer {
1770                         if let Some(referer) = make_referer(&loc, &self.url) {
1771                             self.headers.insert(REFERER, referer);
1772                         }
1773                     }
1774                     let url = self.url.clone();
1775                     self.as_mut().urls().push(url);
1776                     let action = self
1777                         .client
1778                         .redirect_policy
1779                         .check(res.status(), &loc, &self.urls);
1780 
1781                     match action {
1782                         redirect::ActionKind::Follow => {
1783                             debug!("redirecting '{}' to '{}'", self.url, loc);
1784 
1785                             if self.client.https_only && loc.scheme() != "https" {
1786                                 return Poll::Ready(Err(error::redirect(
1787                                     error::url_bad_scheme(loc.clone()),
1788                                     loc,
1789                                 )));
1790                             }
1791 
1792                             self.url = loc;
1793                             let mut headers =
1794                                 std::mem::replace(self.as_mut().headers(), HeaderMap::new());
1795 
1796                             remove_sensitive_headers(&mut headers, &self.url, &self.urls);
1797                             let uri = expect_uri(&self.url);
1798                             let body = match self.body {
1799                                 Some(Some(ref body)) => Body::reusable(body.clone()),
1800                                 _ => Body::empty(),
1801                             };
1802                             let mut req = hyper::Request::builder()
1803                                 .method(self.method.clone())
1804                                 .uri(uri.clone())
1805                                 .body(body.into_stream())
1806                                 .expect("valid request parts");
1807 
1808                             // Add cookies from the cookie store.
1809                             #[cfg(feature = "cookies")]
1810                             {
1811                                 if let Some(ref cookie_store) = self.client.cookie_store {
1812                                     add_cookie_header(&mut headers, &**cookie_store, &self.url);
1813                                 }
1814                             }
1815 
1816                             *req.headers_mut() = headers.clone();
1817                             std::mem::swap(self.as_mut().headers(), &mut headers);
1818                             *self.as_mut().in_flight().get_mut() = self.client.hyper.request(req);
1819                             continue;
1820                         }
1821                         redirect::ActionKind::Stop => {
1822                             debug!("redirect policy disallowed redirection to '{}'", loc);
1823                         }
1824                         redirect::ActionKind::Error(err) => {
1825                             return Poll::Ready(Err(crate::error::redirect(err, self.url.clone())));
1826                         }
1827                     }
1828                 }
1829             }
1830 
1831             debug!("response '{}' for {}", res.status(), self.url);
1832             let res = Response::new(
1833                 res,
1834                 self.url.clone(),
1835                 self.client.accepts,
1836                 self.timeout.take(),
1837             );
1838             return Poll::Ready(Ok(res));
1839         }
1840     }
1841 }
1842 
1843 impl fmt::Debug for Pending {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1844     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1845         match self.inner {
1846             PendingInner::Request(ref req) => f
1847                 .debug_struct("Pending")
1848                 .field("method", &req.method)
1849                 .field("url", &req.url)
1850                 .finish(),
1851             PendingInner::Error(ref err) => f.debug_struct("Pending").field("error", err).finish(),
1852         }
1853     }
1854 }
1855 
make_referer(next: &Url, previous: &Url) -> Option<HeaderValue>1856 fn make_referer(next: &Url, previous: &Url) -> Option<HeaderValue> {
1857     if next.scheme() == "http" && previous.scheme() == "https" {
1858         return None;
1859     }
1860 
1861     let mut referer = previous.clone();
1862     let _ = referer.set_username("");
1863     let _ = referer.set_password(None);
1864     referer.set_fragment(None);
1865     referer.as_str().parse().ok()
1866 }
1867 
1868 #[cfg(feature = "cookies")]
add_cookie_header(headers: &mut HeaderMap, cookie_store: &dyn cookie::CookieStore, url: &Url)1869 fn add_cookie_header(headers: &mut HeaderMap, cookie_store: &dyn cookie::CookieStore, url: &Url) {
1870     if let Some(header) = cookie_store.cookies(url) {
1871         headers.insert(crate::header::COOKIE, header);
1872     }
1873 }
1874 
1875 #[cfg(test)]
1876 mod tests {
1877     #[tokio::test]
execute_request_rejects_invald_urls()1878     async fn execute_request_rejects_invald_urls() {
1879         let url_str = "hxxps://www.rust-lang.org/";
1880         let url = url::Url::parse(url_str).unwrap();
1881         let result = crate::get(url.clone()).await;
1882 
1883         assert!(result.is_err());
1884         let err = result.err().unwrap();
1885         assert!(err.is_builder());
1886         assert_eq!(url_str, err.url().unwrap().as_str());
1887     }
1888 }
1889