Separate default-tls and native-tls features (#749)
To allow for the default-tls to change to a different backend by default, this adds a new `native-tls` optional feature. Any TLS feature that was only available using native-tls now requires the `native-tls` feature to be enabled.
This commit is contained in:
		
							
								
								
									
										3
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @@ -55,6 +55,7 @@ jobs: | |||||||
|           - windows / stable-i686-gnu |           - windows / stable-i686-gnu | ||||||
|           - "feat.: default-tls disabled" |           - "feat.: default-tls disabled" | ||||||
|           - "feat.: rustls-tls" |           - "feat.: rustls-tls" | ||||||
|  |           - "feat.: native-tls" | ||||||
|           - "feat.: default-tls and rustls-tls" |           - "feat.: default-tls and rustls-tls" | ||||||
|           - "feat.: cookies" |           - "feat.: cookies" | ||||||
|           - "feat.: blocking" |           - "feat.: blocking" | ||||||
| @@ -100,6 +101,8 @@ jobs: | |||||||
|             features: "--no-default-features" |             features: "--no-default-features" | ||||||
|           - name: "feat.: rustls-tls" |           - name: "feat.: rustls-tls" | ||||||
|             features: "--no-default-features --features rustls-tls" |             features: "--no-default-features --features rustls-tls" | ||||||
|  |           - name: "feat.: native-tls" | ||||||
|  |             features: "--features native-tls" | ||||||
|           - name: "feat.: default-tls and rustls-tls" |           - name: "feat.: default-tls and rustls-tls" | ||||||
|             features: "--features rustls-tls" |             features: "--features rustls-tls" | ||||||
|           - name: "feat.: cookies" |           - name: "feat.: cookies" | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								Cargo.toml
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								Cargo.toml
									
									
									
									
									
								
							| @@ -18,12 +18,15 @@ all-features = true | |||||||
| [features] | [features] | ||||||
| default = ["default-tls"] | default = ["default-tls"] | ||||||
|  |  | ||||||
| tls = [] | # Note: this doesn't enable the 'native-tls' feature, which adds specific | ||||||
|  | # functionality for it. | ||||||
|  | default-tls = ["hyper-tls", "native-tls-crate", "__tls", "tokio-tls"] | ||||||
|  |  | ||||||
| default-tls = ["hyper-tls", "native-tls", "tls", "tokio-tls"] | # Enables native-tls specific functionality not available by default. | ||||||
| default-tls-vendored = ["default-tls", "native-tls/vendored"] | native-tls = ["default-tls"] | ||||||
|  | native-tls-vendored = ["native-tls", "native-tls-crate/vendored"] | ||||||
|  |  | ||||||
| rustls-tls = ["hyper-rustls", "tokio-rustls", "webpki-roots", "rustls", "tls"] | rustls-tls = ["hyper-rustls", "tokio-rustls", "webpki-roots", "rustls", "__tls"] | ||||||
|  |  | ||||||
| blocking = ["futures-channel", "futures-util/io", "tokio/rt-threaded", "tokio/rt-core"] | blocking = ["futures-channel", "futures-util/io", "tokio/rt-threaded", "tokio/rt-core"] | ||||||
|  |  | ||||||
| @@ -40,6 +43,9 @@ stream = [] | |||||||
| # Internal (PRIVATE!) features used to aid testing. | # Internal (PRIVATE!) features used to aid testing. | ||||||
| # Don't rely on these whatsoever. They may disappear at anytime. | # Don't rely on these whatsoever. They may disappear at anytime. | ||||||
|  |  | ||||||
|  | # Enables common types used for TLS. Useless on its own. | ||||||
|  | __tls = [] | ||||||
|  |  | ||||||
| # When enabled, disable using the cached SYS_PROXIES. | # When enabled, disable using the cached SYS_PROXIES. | ||||||
| __internal_proxy_sys_no_cache = [] | __internal_proxy_sys_no_cache = [] | ||||||
|  |  | ||||||
| @@ -74,7 +80,7 @@ serde_urlencoded = "0.6.1" | |||||||
|  |  | ||||||
| ## default-tls | ## default-tls | ||||||
| hyper-tls = { version = "0.4", optional = true } | hyper-tls = { version = "0.4", optional = true } | ||||||
| native-tls = { version = "0.2", optional = true } | native-tls-crate = { version = "0.2", optional = true, package = "native-tls" } | ||||||
| tokio-tls = { version = "0.3.0", optional = true } | tokio-tls = { version = "0.3.0", optional = true } | ||||||
|  |  | ||||||
| # rustls-tls | # rustls-tls | ||||||
|   | |||||||
| @@ -13,8 +13,8 @@ use http::header::{ | |||||||
| use http::Uri; | use http::Uri; | ||||||
| use http::uri::Scheme; | use http::uri::Scheme; | ||||||
| use hyper::client::ResponseFuture; | use hyper::client::ResponseFuture; | ||||||
| #[cfg(feature = "default-tls")] | #[cfg(feature = "native-tls-crate")] | ||||||
| use native_tls::TlsConnector; | use native_tls_crate::TlsConnector; | ||||||
| use std::future::Future; | use std::future::Future; | ||||||
| use std::pin::Pin; | use std::pin::Pin; | ||||||
| use std::task::{Context, Poll}; | use std::task::{Context, Poll}; | ||||||
| @@ -30,9 +30,9 @@ use crate::connect::Connector; | |||||||
| use crate::cookie; | use crate::cookie; | ||||||
| use crate::into_url::{expect_uri, try_uri}; | use crate::into_url::{expect_uri, try_uri}; | ||||||
| use crate::redirect::{self, remove_sensitive_headers}; | use crate::redirect::{self, remove_sensitive_headers}; | ||||||
| #[cfg(feature = "tls")] | #[cfg(feature = "__tls")] | ||||||
| use crate::tls::TlsBackend; | use crate::tls::TlsBackend; | ||||||
| #[cfg(feature = "tls")] | #[cfg(feature = "__tls")] | ||||||
| use crate::{Certificate, Identity}; | use crate::{Certificate, Identity}; | ||||||
| use crate::{IntoUrl, Method, Proxy, StatusCode, Url}; | use crate::{IntoUrl, Method, Proxy, StatusCode, Url}; | ||||||
|  |  | ||||||
| @@ -60,22 +60,22 @@ struct Config { | |||||||
|     // NOTE: When adding a new field, update `fmt::Debug for ClientBuilder` |     // NOTE: When adding a new field, update `fmt::Debug for ClientBuilder` | ||||||
|     gzip: bool, |     gzip: bool, | ||||||
|     headers: HeaderMap, |     headers: HeaderMap, | ||||||
|     #[cfg(feature = "default-tls")] |     #[cfg(feature = "native-tls")] | ||||||
|     hostname_verification: bool, |     hostname_verification: bool, | ||||||
|     #[cfg(feature = "tls")] |     #[cfg(feature = "__tls")] | ||||||
|     certs_verification: bool, |     certs_verification: bool, | ||||||
|     connect_timeout: Option<Duration>, |     connect_timeout: Option<Duration>, | ||||||
|     max_idle_per_host: usize, |     max_idle_per_host: usize, | ||||||
|     #[cfg(feature = "tls")] |     #[cfg(feature = "__tls")] | ||||||
|     identity: Option<Identity>, |     identity: Option<Identity>, | ||||||
|     proxies: Vec<Proxy>, |     proxies: Vec<Proxy>, | ||||||
|     auto_sys_proxy: bool, |     auto_sys_proxy: bool, | ||||||
|     redirect_policy: redirect::Policy, |     redirect_policy: redirect::Policy, | ||||||
|     referer: bool, |     referer: bool, | ||||||
|     timeout: Option<Duration>, |     timeout: Option<Duration>, | ||||||
|     #[cfg(feature = "tls")] |     #[cfg(feature = "__tls")] | ||||||
|     root_certs: Vec<Certificate>, |     root_certs: Vec<Certificate>, | ||||||
|     #[cfg(feature = "tls")] |     #[cfg(feature = "__tls")] | ||||||
|     tls: TlsBackend, |     tls: TlsBackend, | ||||||
|     http2_only: bool, |     http2_only: bool, | ||||||
|     http1_title_case_headers: bool, |     http1_title_case_headers: bool, | ||||||
| @@ -106,9 +106,9 @@ impl ClientBuilder { | |||||||
|             config: Config { |             config: Config { | ||||||
|                 gzip: cfg!(feature = "gzip"), |                 gzip: cfg!(feature = "gzip"), | ||||||
|                 headers, |                 headers, | ||||||
|                 #[cfg(feature = "default-tls")] |                 #[cfg(feature = "native-tls")] | ||||||
|                 hostname_verification: true, |                 hostname_verification: true, | ||||||
|                 #[cfg(feature = "tls")] |                 #[cfg(feature = "__tls")] | ||||||
|                 certs_verification: true, |                 certs_verification: true, | ||||||
|                 connect_timeout: None, |                 connect_timeout: None, | ||||||
|                 max_idle_per_host: std::usize::MAX, |                 max_idle_per_host: std::usize::MAX, | ||||||
| @@ -117,11 +117,11 @@ impl ClientBuilder { | |||||||
|                 redirect_policy: redirect::Policy::default(), |                 redirect_policy: redirect::Policy::default(), | ||||||
|                 referer: true, |                 referer: true, | ||||||
|                 timeout: None, |                 timeout: None, | ||||||
|                 #[cfg(feature = "tls")] |                 #[cfg(feature = "__tls")] | ||||||
|                 root_certs: Vec::new(), |                 root_certs: Vec::new(), | ||||||
|                 #[cfg(feature = "tls")] |                 #[cfg(feature = "__tls")] | ||||||
|                 identity: None, |                 identity: None, | ||||||
|                 #[cfg(feature = "tls")] |                 #[cfg(feature = "__tls")] | ||||||
|                 tls: TlsBackend::default(), |                 tls: TlsBackend::default(), | ||||||
|                 http2_only: false, |                 http2_only: false, | ||||||
|                 http1_title_case_headers: false, |                 http1_title_case_headers: false, | ||||||
| @@ -150,26 +150,35 @@ impl ClientBuilder { | |||||||
|         let proxies = Arc::new(proxies); |         let proxies = Arc::new(proxies); | ||||||
|  |  | ||||||
|         let mut connector = { |         let mut connector = { | ||||||
|             #[cfg(feature = "tls")] |             #[cfg(feature = "__tls")] | ||||||
|             fn user_agent(headers: &HeaderMap) -> HeaderValue { |             fn user_agent(headers: &HeaderMap) -> HeaderValue { | ||||||
|                 headers[USER_AGENT].clone() |                 headers[USER_AGENT].clone() | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             #[cfg(feature = "tls")] |             #[cfg(feature = "__tls")] | ||||||
|             match config.tls { |             match config.tls { | ||||||
|                 #[cfg(feature = "default-tls")] |                 #[cfg(feature = "default-tls")] | ||||||
|                 TlsBackend::Default => { |                 TlsBackend::Default => { | ||||||
|                     let mut tls = TlsConnector::builder(); |                     let mut tls = TlsConnector::builder(); | ||||||
|  |  | ||||||
|  |                     #[cfg(feature = "native-tls")] | ||||||
|  |                     { | ||||||
|                         tls.danger_accept_invalid_hostnames(!config.hostname_verification); |                         tls.danger_accept_invalid_hostnames(!config.hostname_verification); | ||||||
|  |                     } | ||||||
|  |  | ||||||
|                     tls.danger_accept_invalid_certs(!config.certs_verification); |                     tls.danger_accept_invalid_certs(!config.certs_verification); | ||||||
|  |  | ||||||
|                     for cert in config.root_certs { |                     for cert in config.root_certs { | ||||||
|                         cert.add_to_native_tls(&mut tls); |                         cert.add_to_native_tls(&mut tls); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |                     #[cfg(feature = "native-tls")] | ||||||
|  |                     { | ||||||
|                         if let Some(id) = config.identity { |                         if let Some(id) = config.identity { | ||||||
|                             id.add_to_native_tls(&mut tls)?; |                             id.add_to_native_tls(&mut tls)?; | ||||||
|                         } |                         } | ||||||
|  |                     } | ||||||
|  |  | ||||||
|                     Connector::new_default_tls( |                     Connector::new_default_tls( | ||||||
|                         tls, |                         tls, | ||||||
| @@ -215,7 +224,7 @@ impl ClientBuilder { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             #[cfg(not(feature = "tls"))] |             #[cfg(not(feature = "__tls"))] | ||||||
|             Connector::new(proxies.clone(), config.local_address, config.nodelay)? |             Connector::new(proxies.clone(), config.local_address, config.nodelay)? | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
| @@ -511,9 +520,9 @@ impl ClientBuilder { | |||||||
|     /// |     /// | ||||||
|     /// # Optional |     /// # Optional | ||||||
|     /// |     /// | ||||||
|     /// This requires the optional `default-tls` or `rustls-tls` feature to be |     /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls` | ||||||
|     /// enabled. |     /// feature to be enabled. | ||||||
|     #[cfg(feature = "tls")] |     #[cfg(feature = "__tls")] | ||||||
|     pub fn add_root_certificate(mut self, cert: Certificate) -> ClientBuilder { |     pub fn add_root_certificate(mut self, cert: Certificate) -> ClientBuilder { | ||||||
|         self.config.root_certs.push(cert); |         self.config.root_certs.push(cert); | ||||||
|         self |         self | ||||||
| @@ -523,9 +532,9 @@ impl ClientBuilder { | |||||||
|     /// |     /// | ||||||
|     /// # Optional |     /// # Optional | ||||||
|     /// |     /// | ||||||
|     /// This requires the optional `default-tls` or `rustls-tls` feature to be |     /// This requires the optional `native-tls` or `rustls-tls` feature to be | ||||||
|     /// enabled. |     /// enabled. | ||||||
|     #[cfg(feature = "tls")] |     #[cfg(feature = "__tls")] | ||||||
|     pub fn identity(mut self, identity: Identity) -> ClientBuilder { |     pub fn identity(mut self, identity: Identity) -> ClientBuilder { | ||||||
|         self.config.identity = Some(identity); |         self.config.identity = Some(identity); | ||||||
|         self |         self | ||||||
| @@ -544,8 +553,8 @@ impl ClientBuilder { | |||||||
|     /// |     /// | ||||||
|     /// # Optional |     /// # Optional | ||||||
|     /// |     /// | ||||||
|     /// This requires the optional `default-tls` feature to be enabled. |     /// This requires the optional `native-tls` feature to be enabled. | ||||||
|     #[cfg(feature = "default-tls")] |     #[cfg(feature = "native-tls")] | ||||||
|     pub fn danger_accept_invalid_hostnames( |     pub fn danger_accept_invalid_hostnames( | ||||||
|         mut self, |         mut self, | ||||||
|         accept_invalid_hostname: bool, |         accept_invalid_hostname: bool, | ||||||
| @@ -568,9 +577,9 @@ impl ClientBuilder { | |||||||
|     /// |     /// | ||||||
|     /// # Optional |     /// # Optional | ||||||
|     /// |     /// | ||||||
|     /// This requires the optional `default-tls` or `rustls-tls` feature to be |     /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls` | ||||||
|     /// enabled. |     /// feature to be enabled. | ||||||
|     #[cfg(feature = "tls")] |     #[cfg(feature = "__tls")] | ||||||
|     pub fn danger_accept_invalid_certs(mut self, accept_invalid_certs: bool) -> ClientBuilder { |     pub fn danger_accept_invalid_certs(mut self, accept_invalid_certs: bool) -> ClientBuilder { | ||||||
|         self.config.certs_verification = !accept_invalid_certs; |         self.config.certs_verification = !accept_invalid_certs; | ||||||
|         self |         self | ||||||
| @@ -583,9 +592,9 @@ impl ClientBuilder { | |||||||
|     /// |     /// | ||||||
|     /// # Optional |     /// # Optional | ||||||
|     /// |     /// | ||||||
|     /// This requires the optional `default-tls` feature to be enabled. |     /// This requires the optional `native-tls` feature to be enabled. | ||||||
|     #[cfg(feature = "default-tls")] |     #[cfg(feature = "native-tls")] | ||||||
|     pub fn use_default_tls(mut self) -> ClientBuilder { |     pub fn use_native_tls(mut self) -> ClientBuilder { | ||||||
|         self.config.tls = TlsBackend::Default; |         self.config.tls = TlsBackend::Default; | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
| @@ -888,21 +897,21 @@ impl Config { | |||||||
|             f.field("tcp_nodelay", &true); |             f.field("tcp_nodelay", &true); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #[cfg(feature = "default-tls")] |         #[cfg(feature = "native-tls")] | ||||||
|         { |         { | ||||||
|             if !self.hostname_verification { |             if !self.hostname_verification { | ||||||
|                 f.field("danger_accept_invalid_hostnames", &true); |                 f.field("danger_accept_invalid_hostnames", &true); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #[cfg(feature = "tls")] |         #[cfg(feature = "__tls")] | ||||||
|         { |         { | ||||||
|             if !self.certs_verification { |             if !self.certs_verification { | ||||||
|                 f.field("danger_accept_invalid_certs", &true); |                 f.field("danger_accept_invalid_certs", &true); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         #[cfg(all(feature = "default-tls", feature = "rustls-tls"))] |         #[cfg(all(feature = "native-tls-crate", feature = "rustls-tls"))] | ||||||
|         { |         { | ||||||
|             f.field("tls_backend", &self.tls); |             f.field("tls_backend", &self.tls); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ use super::request::{Request, RequestBuilder}; | |||||||
| use super::response::Response; | use super::response::Response; | ||||||
| use super::wait; | use super::wait; | ||||||
| use crate::{async_impl, header, IntoUrl, Method, Proxy, redirect}; | use crate::{async_impl, header, IntoUrl, Method, Proxy, redirect}; | ||||||
| #[cfg(feature = "tls")] | #[cfg(feature = "__tls")] | ||||||
| use crate::{Certificate, Identity}; | use crate::{Certificate, Identity}; | ||||||
|  |  | ||||||
| /// A `Client` to make Requests with. | /// A `Client` to make Requests with. | ||||||
| @@ -331,45 +331,15 @@ impl ClientBuilder { | |||||||
|     /// |     /// | ||||||
|     /// # Optional |     /// # Optional | ||||||
|     /// |     /// | ||||||
|     /// This requires the optional `default-tls` or `rustls-tls` feature to be |     /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls` | ||||||
|     /// enabled. |     /// feature to be enabled. | ||||||
|     #[cfg(feature = "tls")] |     #[cfg(feature = "__tls")] | ||||||
|     pub fn add_root_certificate(self, cert: Certificate) -> ClientBuilder { |     pub fn add_root_certificate(self, cert: Certificate) -> ClientBuilder { | ||||||
|         self.with_inner(move |inner| inner.add_root_certificate(cert)) |         self.with_inner(move |inner| inner.add_root_certificate(cert)) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Sets the identity to be used for client certificate authentication. |     /// Sets the identity to be used for client certificate authentication. | ||||||
|     /// |     #[cfg(feature = "__tls")] | ||||||
|     /// # Example |  | ||||||
|     /// |  | ||||||
|     /// ``` |  | ||||||
|     /// # use std::fs::File; |  | ||||||
|     /// # use std::io::Read; |  | ||||||
|     /// # fn build_client() -> Result<(), Box<std::error::Error>> { |  | ||||||
|     /// // read a local PKCS12 bundle |  | ||||||
|     /// let mut buf = Vec::new(); |  | ||||||
|     /// |  | ||||||
|     /// #[cfg(feature = "default-tls")] |  | ||||||
|     /// File::open("my-ident.pfx")?.read_to_end(&mut buf)?; |  | ||||||
|     /// #[cfg(feature = "rustls-tls")] |  | ||||||
|     /// File::open("my-ident.pem")?.read_to_end(&mut buf)?; |  | ||||||
|     /// |  | ||||||
|     /// #[cfg(feature = "default-tls")] |  | ||||||
|     /// // create an Identity from the PKCS#12 archive |  | ||||||
|     /// let pkcs12 = reqwest::Identity::from_pkcs12_der(&buf, "my-privkey-password")?; |  | ||||||
|     /// #[cfg(feature = "rustls-tls")] |  | ||||||
|     /// // create an Identity from the PEM file |  | ||||||
|     /// let pkcs12 = reqwest::Identity::from_pem(&buf)?; |  | ||||||
|     /// |  | ||||||
|     /// // get a client builder |  | ||||||
|     /// let client = reqwest::blocking::Client::builder() |  | ||||||
|     ///     .identity(pkcs12) |  | ||||||
|     ///     .build()?; |  | ||||||
|     /// # drop(client); |  | ||||||
|     /// # Ok(()) |  | ||||||
|     /// # } |  | ||||||
|     /// ``` |  | ||||||
|     #[cfg(feature = "tls")] |  | ||||||
|     pub fn identity(self, identity: Identity) -> ClientBuilder { |     pub fn identity(self, identity: Identity) -> ClientBuilder { | ||||||
|         self.with_inner(move |inner| inner.identity(identity)) |         self.with_inner(move |inner| inner.identity(identity)) | ||||||
|     } |     } | ||||||
| @@ -384,7 +354,11 @@ impl ClientBuilder { | |||||||
|     /// hostname verification is not used, any valid certificate for any |     /// hostname verification is not used, any valid certificate for any | ||||||
|     /// site will be trusted for use from any other. This introduces a |     /// site will be trusted for use from any other. This introduces a | ||||||
|     /// significant vulnerability to man-in-the-middle attacks. |     /// significant vulnerability to man-in-the-middle attacks. | ||||||
|     #[cfg(feature = "default-tls")] |     /// | ||||||
|  |     /// # Optional | ||||||
|  |     /// | ||||||
|  |     /// This requires the optional `native-tls` feature to be enabled. | ||||||
|  |     #[cfg(feature = "native-tls")] | ||||||
|     pub fn danger_accept_invalid_hostnames(self, accept_invalid_hostname: bool) -> ClientBuilder { |     pub fn danger_accept_invalid_hostnames(self, accept_invalid_hostname: bool) -> ClientBuilder { | ||||||
|         self.with_inner(|inner| inner.danger_accept_invalid_hostnames(accept_invalid_hostname)) |         self.with_inner(|inner| inner.danger_accept_invalid_hostnames(accept_invalid_hostname)) | ||||||
|     } |     } | ||||||
| @@ -400,7 +374,7 @@ impl ClientBuilder { | |||||||
|     /// will be trusted for use. This includes expired certificates. This |     /// will be trusted for use. This includes expired certificates. This | ||||||
|     /// introduces significant vulnerabilities, and should only be used |     /// introduces significant vulnerabilities, and should only be used | ||||||
|     /// as a last resort. |     /// as a last resort. | ||||||
|     #[cfg(feature = "tls")] |     #[cfg(feature = "__tls")] | ||||||
|     pub fn danger_accept_invalid_certs(self, accept_invalid_certs: bool) -> ClientBuilder { |     pub fn danger_accept_invalid_certs(self, accept_invalid_certs: bool) -> ClientBuilder { | ||||||
|         self.with_inner(|inner| inner.danger_accept_invalid_certs(accept_invalid_certs)) |         self.with_inner(|inner| inner.danger_accept_invalid_certs(accept_invalid_certs)) | ||||||
|     } |     } | ||||||
| @@ -412,10 +386,10 @@ impl ClientBuilder { | |||||||
|     /// |     /// | ||||||
|     /// # Optional |     /// # Optional | ||||||
|     /// |     /// | ||||||
|     /// This requires the optional `default-tls` feature to be enabled. |     /// This requires the optional `native-tls` feature to be enabled. | ||||||
|     #[cfg(feature = "default-tls")] |     #[cfg(feature = "native-tls")] | ||||||
|     pub fn use_default_tls(self) -> ClientBuilder { |     pub fn use_native_tls(self) -> ClientBuilder { | ||||||
|         self.with_inner(move |inner| inner.use_default_tls()) |         self.with_inner(move |inner| inner.use_native_tls()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Force using the Rustls TLS backend. |     /// Force using the Rustls TLS backend. | ||||||
|   | |||||||
| @@ -3,9 +3,9 @@ use http::uri::{Scheme, Authority}; | |||||||
| use http::Uri; | use http::Uri; | ||||||
| use hyper::client::connect::{Connected, Connection}; | use hyper::client::connect::{Connected, Connection}; | ||||||
| use tokio::io::{AsyncRead, AsyncWrite}; | use tokio::io::{AsyncRead, AsyncWrite}; | ||||||
| #[cfg(feature = "default-tls")] | #[cfg(feature = "native-tls-crate")] | ||||||
| use native_tls::{TlsConnector, TlsConnectorBuilder}; | use native_tls_crate::{TlsConnector, TlsConnectorBuilder}; | ||||||
| #[cfg(feature = "tls")] | #[cfg(feature = "__tls")] | ||||||
| use http::header::HeaderValue; | use http::header::HeaderValue; | ||||||
| use bytes::{Buf, BufMut}; | use bytes::{Buf, BufMut}; | ||||||
|  |  | ||||||
| @@ -38,15 +38,15 @@ pub(crate) struct Connector { | |||||||
|     inner: Inner, |     inner: Inner, | ||||||
|     proxies: Arc<Vec<Proxy>>, |     proxies: Arc<Vec<Proxy>>, | ||||||
|     timeout: Option<Duration>, |     timeout: Option<Duration>, | ||||||
|     #[cfg(feature = "tls")] |     #[cfg(feature = "__tls")] | ||||||
|     nodelay: bool, |     nodelay: bool, | ||||||
|     #[cfg(feature = "tls")] |     #[cfg(feature = "__tls")] | ||||||
|     user_agent: HeaderValue, |     user_agent: HeaderValue, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
| enum Inner { | enum Inner { | ||||||
|     #[cfg(not(feature = "tls"))] |     #[cfg(not(feature = "__tls"))] | ||||||
|     Http(HttpConnector), |     Http(HttpConnector), | ||||||
|     #[cfg(feature = "default-tls")] |     #[cfg(feature = "default-tls")] | ||||||
|     DefaultTls(HttpConnector, TlsConnector), |     DefaultTls(HttpConnector, TlsConnector), | ||||||
| @@ -59,7 +59,7 @@ enum Inner { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl Connector { | impl Connector { | ||||||
|     #[cfg(not(feature = "tls"))] |     #[cfg(not(feature = "__tls"))] | ||||||
|     pub(crate) fn new<T>( |     pub(crate) fn new<T>( | ||||||
|         proxies: Arc<Vec<Proxy>>, |         proxies: Arc<Vec<Proxy>>, | ||||||
|         local_addr: T, |         local_addr: T, | ||||||
| @@ -199,7 +199,7 @@ impl Connector { | |||||||
|                     Ok((Box::new(io) as Conn, connected)) |                     Ok((Box::new(io) as Conn, connected)) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             #[cfg(not(feature = "tls"))] |             #[cfg(not(feature = "__tls"))] | ||||||
|             Inner::Http(_) => socks::connect(proxy, dst, dns), |             Inner::Http(_) => socks::connect(proxy, dst, dns), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -210,7 +210,7 @@ impl Connector { | |||||||
|         is_proxy: bool, |         is_proxy: bool, | ||||||
|     ) -> Result<Conn, BoxError> { |     ) -> Result<Conn, BoxError> { | ||||||
|         match self.inner { |         match self.inner { | ||||||
|             #[cfg(not(feature = "tls"))] |             #[cfg(not(feature = "__tls"))] | ||||||
|             Inner::Http(mut http) => { |             Inner::Http(mut http) => { | ||||||
|                 let io = http.call(dst).await?; |                 let io = http.call(dst).await?; | ||||||
|                 Ok(Conn { |                 Ok(Conn { | ||||||
| @@ -281,7 +281,7 @@ impl Connector { | |||||||
|         }; |         }; | ||||||
|  |  | ||||||
|  |  | ||||||
|         #[cfg(feature = "tls")] |         #[cfg(feature = "__tls")] | ||||||
|         let auth = _auth; |         let auth = _auth; | ||||||
|  |  | ||||||
|         match &self.inner { |         match &self.inner { | ||||||
| @@ -352,7 +352,7 @@ impl Connector { | |||||||
|                     }); |                     }); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             #[cfg(not(feature = "tls"))] |             #[cfg(not(feature = "__tls"))] | ||||||
|             Inner::Http(_) => (), |             Inner::Http(_) => (), | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -510,7 +510,7 @@ impl AsyncWrite for Conn { | |||||||
| pub(crate) type Connecting = | pub(crate) type Connecting = | ||||||
|     Pin<Box<dyn Future<Output = Result<Conn, BoxError>> + Send>>; |     Pin<Box<dyn Future<Output = Result<Conn, BoxError>> + Send>>; | ||||||
|  |  | ||||||
| #[cfg(feature = "tls")] | #[cfg(feature = "__tls")] | ||||||
| async fn tunnel<T>( | async fn tunnel<T>( | ||||||
|     mut conn: T, |     mut conn: T, | ||||||
|     host: String, |     host: String, | ||||||
| @@ -586,7 +586,7 @@ where | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| #[cfg(feature = "tls")] | #[cfg(feature = "__tls")] | ||||||
| fn tunnel_eof() -> io::Error { | fn tunnel_eof() -> io::Error { | ||||||
|     io::Error::new( |     io::Error::new( | ||||||
|         io::ErrorKind::UnexpectedEof, |         io::ErrorKind::UnexpectedEof, | ||||||
| @@ -834,7 +834,7 @@ mod socks { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| #[cfg(feature = "tls")] | #[cfg(feature = "__tls")] | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| mod tests { | mod tests { | ||||||
|     use super::tunnel; |     use super::tunnel; | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/lib.rs
									
									
									
									
									
								
							| @@ -159,9 +159,11 @@ | |||||||
| //! The following are a list of [Cargo features][cargo-features] that can be | //! The following are a list of [Cargo features][cargo-features] that can be | ||||||
| //! enabled or disabled: | //! enabled or disabled: | ||||||
| //! | //! | ||||||
| //! - **default-tls** *(enabled by default)*: Provides TLS support via the | //! - **default-tls** *(enabled by default)*: Provides TLS support to connect | ||||||
| //!   `native-tls` library to connect over HTTPS. | //!   over HTTPS. | ||||||
| //! - **default-tls-vendored**: Enables the `vendored` feature of `native-tls`. | //! - **native-tls**: Enables TLS functionality provided by `native-tls`. | ||||||
|  | //! - **native-tls-vendored**: Enables the `vendored` feature of `native-tls`. | ||||||
|  | //! - **rustls-tls**: Enables TLS functionality provided by `rustls`. | ||||||
| //! - **blocking**: Provides the [blocking][] client API. | //! - **blocking**: Provides the [blocking][] client API. | ||||||
| //! - **cookies**: Provides cookie session support. | //! - **cookies**: Provides cookie session support. | ||||||
| //! - **gzip**: Provides response body gzip decompression. | //! - **gzip**: Provides response body gzip decompression. | ||||||
| @@ -179,7 +181,6 @@ | |||||||
| //! [Proxy]: ./struct.Proxy.html | //! [Proxy]: ./struct.Proxy.html | ||||||
| //! [cargo-features]: https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section | //! [cargo-features]: https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section | ||||||
|  |  | ||||||
| ////! - **rustls-tls**: Provides TLS support via the `rustls` library. |  | ||||||
| ////! - **socks**: Provides SOCKS5 proxy support. | ////! - **socks**: Provides SOCKS5 proxy support. | ||||||
| ////! - **trust-dns**: Enables a trust-dns async resolver instead of default | ////! - **trust-dns**: Enables a trust-dns async resolver instead of default | ||||||
| ////!   threadpool using `getaddrinfo`. | ////!   threadpool using `getaddrinfo`. | ||||||
| @@ -278,7 +279,7 @@ if_hyper! { | |||||||
|         multipart, Body, Client, ClientBuilder, Request, RequestBuilder, Response, ResponseBuilderExt, |         multipart, Body, Client, ClientBuilder, Request, RequestBuilder, Response, ResponseBuilderExt, | ||||||
|     }; |     }; | ||||||
|     pub use self::proxy::Proxy; |     pub use self::proxy::Proxy; | ||||||
|     #[cfg(feature = "tls")] |     #[cfg(feature = "__tls")] | ||||||
|     pub use self::tls::{Certificate, Identity}; |     pub use self::tls::{Certificate, Identity}; | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -292,7 +293,7 @@ if_hyper! { | |||||||
|     //mod dns; |     //mod dns; | ||||||
|     mod proxy; |     mod proxy; | ||||||
|     pub mod redirect; |     pub mod redirect; | ||||||
|     #[cfg(feature = "tls")] |     #[cfg(feature = "__tls")] | ||||||
|     mod tls; |     mod tls; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										48
									
								
								src/tls.rs
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								src/tls.rs
									
									
									
									
									
								
							| @@ -4,11 +4,11 @@ use std::fmt; | |||||||
| #[cfg(feature = "rustls-tls")] | #[cfg(feature = "rustls-tls")] | ||||||
| use tokio_rustls::webpki::DNSNameRef; | use tokio_rustls::webpki::DNSNameRef; | ||||||
|  |  | ||||||
| /// Represent a server X509 certificate. | /// Represents a server X509 certificate. | ||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
| pub struct Certificate { | pub struct Certificate { | ||||||
|     #[cfg(feature = "default-tls")] |     #[cfg(feature = "native-tls-crate")] | ||||||
|     native: native_tls::Certificate, |     native: native_tls_crate::Certificate, | ||||||
|     #[cfg(feature = "rustls-tls")] |     #[cfg(feature = "rustls-tls")] | ||||||
|     original: Cert, |     original: Cert, | ||||||
| } | } | ||||||
| @@ -20,14 +20,18 @@ enum Cert { | |||||||
|     Pem(Vec<u8>), |     Pem(Vec<u8>), | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Represent a private key and X509 cert as a client certificate. | /// Represents a private key and X509 cert as a client certificate. | ||||||
| pub struct Identity { | pub struct Identity { | ||||||
|  |     #[cfg_attr( | ||||||
|  |         not(any(feature = "native-tls", feature = "rustls-tls")), | ||||||
|  |         allow(unused) | ||||||
|  |     )] | ||||||
|     inner: ClientCert, |     inner: ClientCert, | ||||||
| } | } | ||||||
|  |  | ||||||
| enum ClientCert { | enum ClientCert { | ||||||
|     #[cfg(feature = "default-tls")] |     #[cfg(feature = "native-tls")] | ||||||
|     Pkcs12(native_tls::Identity), |     Pkcs12(native_tls_crate::Identity), | ||||||
|     #[cfg(feature = "rustls-tls")] |     #[cfg(feature = "rustls-tls")] | ||||||
|     Pem { |     Pem { | ||||||
|         key: rustls::PrivateKey, |         key: rustls::PrivateKey, | ||||||
| @@ -54,8 +58,8 @@ impl Certificate { | |||||||
|     /// ``` |     /// ``` | ||||||
|     pub fn from_der(der: &[u8]) -> crate::Result<Certificate> { |     pub fn from_der(der: &[u8]) -> crate::Result<Certificate> { | ||||||
|         Ok(Certificate { |         Ok(Certificate { | ||||||
|             #[cfg(feature = "default-tls")] |             #[cfg(feature = "native-tls-crate")] | ||||||
|             native: native_tls::Certificate::from_der(der).map_err(crate::error::builder)?, |             native: native_tls_crate::Certificate::from_der(der).map_err(crate::error::builder)?, | ||||||
|             #[cfg(feature = "rustls-tls")] |             #[cfg(feature = "rustls-tls")] | ||||||
|             original: Cert::Der(der.to_owned()), |             original: Cert::Der(der.to_owned()), | ||||||
|         }) |         }) | ||||||
| @@ -79,15 +83,15 @@ impl Certificate { | |||||||
|     /// ``` |     /// ``` | ||||||
|     pub fn from_pem(pem: &[u8]) -> crate::Result<Certificate> { |     pub fn from_pem(pem: &[u8]) -> crate::Result<Certificate> { | ||||||
|         Ok(Certificate { |         Ok(Certificate { | ||||||
|             #[cfg(feature = "default-tls")] |             #[cfg(feature = "native-tls-crate")] | ||||||
|             native: native_tls::Certificate::from_pem(pem).map_err(crate::error::builder)?, |             native: native_tls_crate::Certificate::from_pem(pem).map_err(crate::error::builder)?, | ||||||
|             #[cfg(feature = "rustls-tls")] |             #[cfg(feature = "rustls-tls")] | ||||||
|             original: Cert::Pem(pem.to_owned()), |             original: Cert::Pem(pem.to_owned()), | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[cfg(feature = "default-tls")] |     #[cfg(feature = "native-tls-crate")] | ||||||
|     pub(crate) fn add_to_native_tls(self, tls: &mut native_tls::TlsConnectorBuilder) { |     pub(crate) fn add_to_native_tls(self, tls: &mut native_tls_crate::TlsConnectorBuilder) { | ||||||
|         tls.add_root_certificate(self.native); |         tls.add_root_certificate(self.native); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -147,11 +151,15 @@ impl Identity { | |||||||
|     /// # Ok(()) |     /// # Ok(()) | ||||||
|     /// # } |     /// # } | ||||||
|     /// ``` |     /// ``` | ||||||
|     #[cfg(feature = "default-tls")] |     /// | ||||||
|  |     /// # Optional | ||||||
|  |     /// | ||||||
|  |     /// This requires the `native-tls` Cargo feature enabled. | ||||||
|  |     #[cfg(feature = "native-tls")] | ||||||
|     pub fn from_pkcs12_der(der: &[u8], password: &str) -> crate::Result<Identity> { |     pub fn from_pkcs12_der(der: &[u8], password: &str) -> crate::Result<Identity> { | ||||||
|         Ok(Identity { |         Ok(Identity { | ||||||
|             inner: ClientCert::Pkcs12( |             inner: ClientCert::Pkcs12( | ||||||
|                 native_tls::Identity::from_pkcs12(der, password).map_err(crate::error::builder)?, |                 native_tls_crate::Identity::from_pkcs12(der, password).map_err(crate::error::builder)?, | ||||||
|             ), |             ), | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| @@ -175,6 +183,10 @@ impl Identity { | |||||||
|     /// # Ok(()) |     /// # Ok(()) | ||||||
|     /// # } |     /// # } | ||||||
|     /// ``` |     /// ``` | ||||||
|  |     /// | ||||||
|  |     /// # Optional | ||||||
|  |     /// | ||||||
|  |     /// This requires the `rustls-tls` Cargo feature enabled. | ||||||
|     #[cfg(feature = "rustls-tls")] |     #[cfg(feature = "rustls-tls")] | ||||||
|     pub fn from_pem(buf: &[u8]) -> crate::Result<Identity> { |     pub fn from_pem(buf: &[u8]) -> crate::Result<Identity> { | ||||||
|         use rustls::internal::pemfile; |         use rustls::internal::pemfile; | ||||||
| @@ -214,10 +226,10 @@ impl Identity { | |||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[cfg(feature = "default-tls")] |     #[cfg(feature = "native-tls")] | ||||||
|     pub(crate) fn add_to_native_tls( |     pub(crate) fn add_to_native_tls( | ||||||
|         self, |         self, | ||||||
|         tls: &mut native_tls::TlsConnectorBuilder, |         tls: &mut native_tls_crate::TlsConnectorBuilder, | ||||||
|     ) -> crate::Result<()> { |     ) -> crate::Result<()> { | ||||||
|         match self.inner { |         match self.inner { | ||||||
|             ClientCert::Pkcs12(id) => { |             ClientCert::Pkcs12(id) => { | ||||||
| @@ -236,7 +248,7 @@ impl Identity { | |||||||
|                 tls.set_single_client_cert(certs, key); |                 tls.set_single_client_cert(certs, key); | ||||||
|                 Ok(()) |                 Ok(()) | ||||||
|             } |             } | ||||||
|             #[cfg(feature = "default-tls")] |             #[cfg(feature = "native-tls")] | ||||||
|             ClientCert::Pkcs12(..) => Err(crate::error::builder("incompatible TLS identity type")), |             ClientCert::Pkcs12(..) => Err(crate::error::builder("incompatible TLS identity type")), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -308,7 +320,7 @@ mod tests { | |||||||
|         Certificate::from_pem(b"not pem").unwrap_err(); |         Certificate::from_pem(b"not pem").unwrap_err(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[cfg(feature = "default-tls")] |     #[cfg(feature = "native-tls")] | ||||||
|     #[test] |     #[test] | ||||||
|     fn identity_from_pkcs12_der_invalid() { |     fn identity_from_pkcs12_der_invalid() { | ||||||
|         Identity::from_pkcs12_der(b"not der", "nope").unwrap_err(); |         Identity::from_pkcs12_der(b"not der", "nope").unwrap_err(); | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| #[cfg(feature = "tls")] | #[cfg(feature = "__tls")] | ||||||
| #[tokio::test] | #[tokio::test] | ||||||
| async fn test_badssl_modern() { | async fn test_badssl_modern() { | ||||||
|     let text = reqwest::get("https://mozilla-modern.badssl.com/") |     let text = reqwest::get("https://mozilla-modern.badssl.com/") | ||||||
| @@ -29,7 +29,7 @@ async fn test_rustls_badssl_modern() { | |||||||
|     assert!(text.contains("<title>mozilla-modern.badssl.com</title>")); |     assert!(text.contains("<title>mozilla-modern.badssl.com</title>")); | ||||||
| } | } | ||||||
|  |  | ||||||
| #[cfg(feature = "tls")] | #[cfg(feature = "__tls")] | ||||||
| #[tokio::test] | #[tokio::test] | ||||||
| async fn test_badssl_self_signed() { | async fn test_badssl_self_signed() { | ||||||
|     let text = reqwest::Client::builder() |     let text = reqwest::Client::builder() | ||||||
| @@ -47,7 +47,7 @@ async fn test_badssl_self_signed() { | |||||||
|     assert!(text.contains("<title>self-signed.badssl.com</title>")); |     assert!(text.contains("<title>self-signed.badssl.com</title>")); | ||||||
| } | } | ||||||
|  |  | ||||||
| #[cfg(feature = "default-tls")] | #[cfg(feature = "native-tls")] | ||||||
| #[tokio::test] | #[tokio::test] | ||||||
| async fn test_badssl_wrong_host() { | async fn test_badssl_wrong_host() { | ||||||
|     let text = reqwest::Client::builder() |     let text = reqwest::Client::builder() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user