Implement ability to disable trust-dns in ClientBuilder.
				
					
				
			This commit is contained in:
		| @@ -31,7 +31,7 @@ use log::debug; | |||||||
| use super::request::{Request, RequestBuilder}; | use super::request::{Request, RequestBuilder}; | ||||||
| use super::response::Response; | use super::response::Response; | ||||||
| use super::Body; | use super::Body; | ||||||
| use crate::connect::Connector; | use crate::connect::{Connector, HttpConnector}; | ||||||
| #[cfg(feature = "cookies")] | #[cfg(feature = "cookies")] | ||||||
| use crate::cookie; | use crate::cookie; | ||||||
| use crate::into_url::{expect_uri, try_uri}; | use crate::into_url::{expect_uri, try_uri}; | ||||||
| @@ -91,6 +91,7 @@ struct Config { | |||||||
|     nodelay: bool, |     nodelay: bool, | ||||||
|     #[cfg(feature = "cookies")] |     #[cfg(feature = "cookies")] | ||||||
|     cookie_store: Option<cookie::CookieStore>, |     cookie_store: Option<cookie::CookieStore>, | ||||||
|  |     trust_dns: bool, | ||||||
|     error: Option<crate::Error>, |     error: Option<crate::Error>, | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -138,6 +139,7 @@ impl ClientBuilder { | |||||||
|                 http2_initial_connection_window_size: None, |                 http2_initial_connection_window_size: None, | ||||||
|                 local_address: None, |                 local_address: None, | ||||||
|                 nodelay: false, |                 nodelay: false, | ||||||
|  |                 trust_dns: cfg!(feature = "trust-dns"), | ||||||
|                 #[cfg(feature = "cookies")] |                 #[cfg(feature = "cookies")] | ||||||
|                 cookie_store: None, |                 cookie_store: None, | ||||||
|             }, |             }, | ||||||
| @@ -169,6 +171,14 @@ impl ClientBuilder { | |||||||
|                 headers.get(USER_AGENT).cloned() |                 headers.get(USER_AGENT).cloned() | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             let http = match config.trust_dns { | ||||||
|  |                 false => HttpConnector::new_gai(), | ||||||
|  |                 #[cfg(feature = "trust-dns")] | ||||||
|  |                 true => HttpConnector::new_trust_dns()?, | ||||||
|  |                 #[cfg(not(feature = "trust-dns"))] | ||||||
|  |                 true => unreachable!("trust-dns shouldn't be enabled unless the feature is"), | ||||||
|  |             }; | ||||||
|  |  | ||||||
|             #[cfg(feature = "__tls")] |             #[cfg(feature = "__tls")] | ||||||
|             match config.tls { |             match config.tls { | ||||||
|                 #[cfg(feature = "default-tls")] |                 #[cfg(feature = "default-tls")] | ||||||
| @@ -195,6 +205,7 @@ impl ClientBuilder { | |||||||
|  |  | ||||||
|  |  | ||||||
|                     Connector::new_default_tls( |                     Connector::new_default_tls( | ||||||
|  |                         http, | ||||||
|                         tls, |                         tls, | ||||||
|                         proxies.clone(), |                         proxies.clone(), | ||||||
|                         user_agent(&config.headers), |                         user_agent(&config.headers), | ||||||
| @@ -205,6 +216,7 @@ impl ClientBuilder { | |||||||
|                 #[cfg(feature = "native-tls")] |                 #[cfg(feature = "native-tls")] | ||||||
|                 TlsBackend::BuiltNativeTls(conn) => { |                 TlsBackend::BuiltNativeTls(conn) => { | ||||||
|                     Connector::from_built_default_tls( |                     Connector::from_built_default_tls( | ||||||
|  |                         http, | ||||||
|                         conn, |                         conn, | ||||||
|                         proxies.clone(), |                         proxies.clone(), | ||||||
|                         user_agent(&config.headers), |                         user_agent(&config.headers), | ||||||
| @@ -214,6 +226,7 @@ impl ClientBuilder { | |||||||
|                 #[cfg(feature = "rustls-tls")] |                 #[cfg(feature = "rustls-tls")] | ||||||
|                 TlsBackend::BuiltRustls(conn) => { |                 TlsBackend::BuiltRustls(conn) => { | ||||||
|                     Connector::new_rustls_tls( |                     Connector::new_rustls_tls( | ||||||
|  |                         http, | ||||||
|                         conn, |                         conn, | ||||||
|                         proxies.clone(), |                         proxies.clone(), | ||||||
|                         user_agent(&config.headers), |                         user_agent(&config.headers), | ||||||
| @@ -247,6 +260,7 @@ impl ClientBuilder { | |||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     Connector::new_rustls_tls( |                     Connector::new_rustls_tls( | ||||||
|  |                         http, | ||||||
|                         tls, |                         tls, | ||||||
|                         proxies.clone(), |                         proxies.clone(), | ||||||
|                         user_agent(&config.headers), |                         user_agent(&config.headers), | ||||||
| @@ -266,7 +280,7 @@ impl ClientBuilder { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             #[cfg(not(feature = "__tls"))] |             #[cfg(not(feature = "__tls"))] | ||||||
|             Connector::new(proxies.clone(), config.local_address, config.nodelay)? |             Connector::new(http, proxies.clone(), config.local_address, config.nodelay)? | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         connector.set_timeout(config.connect_timeout); |         connector.set_timeout(config.connect_timeout); | ||||||
| @@ -793,6 +807,36 @@ impl ClientBuilder { | |||||||
|         self.config.tls = crate::tls::TlsBackend::UnknownPreconfigured; |         self.config.tls = crate::tls::TlsBackend::UnknownPreconfigured; | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /// Enables the [trust-dns](trust_dns_resolver) async resolver instead of a default threadpool using `getaddrinfo`. | ||||||
|  |     /// | ||||||
|  |     /// If the `trust-dns` feature is turned on, the default option is enabled. | ||||||
|  |     /// | ||||||
|  |     /// # Optional | ||||||
|  |     /// | ||||||
|  |     /// This requires the optional `trust-dns` feature to be enabled | ||||||
|  |     #[cfg(feature = "trust-dns")] | ||||||
|  |     pub fn trust_dns(mut self, enable: bool) -> ClientBuilder { | ||||||
|  |         self.config.trust_dns = enable; | ||||||
|  |         self | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// Disables the trust-dns async resolver. | ||||||
|  |     /// | ||||||
|  |     /// This method exists even if the optional `trust-dns` feature is not enabled. | ||||||
|  |     /// This can be used to ensure a `Client` doesn't use the trust-dns async resolver | ||||||
|  |     /// even if another dependency were to enable the optional `trust-dns` feature. | ||||||
|  |     pub fn no_trust_dns(self) -> ClientBuilder { | ||||||
|  |         #[cfg(feature = "trust-dns")] | ||||||
|  |         { | ||||||
|  |             self.trust_dns(false) | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         #[cfg(not(feature = "trust-dns"))] | ||||||
|  |         { | ||||||
|  |             self | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| type HyperClient = hyper::Client<Connector, super::body::ImplStream>; | type HyperClient = hyper::Client<Connector, super::body::ImplStream>; | ||||||
|   | |||||||
| @@ -481,6 +481,27 @@ impl ClientBuilder { | |||||||
|         self.with_inner(move |inner| inner.use_preconfigured_tls(tls)) |         self.with_inner(move |inner| inner.use_preconfigured_tls(tls)) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /// Enables the [trust-dns](trust_dns_resolver) async resolver instead of a default threadpool using `getaddrinfo`. | ||||||
|  |     /// | ||||||
|  |     /// If the `trust-dns` feature is turned on, the default option is enabled. | ||||||
|  |     /// | ||||||
|  |     /// # Optional | ||||||
|  |     /// | ||||||
|  |     /// This requires the optional `trust-dns` feature to be enabled | ||||||
|  |     #[cfg(feature = "trust-dns")] | ||||||
|  |     pub fn trust_dns(self, enable: bool) -> ClientBuilder { | ||||||
|  |         self.with_inner(|inner| inner.trust_dns(enable)) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// Disables the trust-dns async resolver. | ||||||
|  |     /// | ||||||
|  |     /// This method exists even if the optional `trust-dns` feature is not enabled. | ||||||
|  |     /// This can be used to ensure a `Client` doesn't use the trust-dns async resolver | ||||||
|  |     /// even if another dependency were to enable the optional `trust-dns` feature. | ||||||
|  |     pub fn no_trust_dns(self) -> ClientBuilder { | ||||||
|  |         self.with_inner(|inner| inner.no_trust_dns()) | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // private |     // private | ||||||
|  |  | ||||||
|     fn with_inner<F>(mut self, func: F) -> ClientBuilder |     fn with_inner<F>(mut self, func: F) -> ClientBuilder | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ use tokio::io::{AsyncRead, AsyncWrite}; | |||||||
| use native_tls_crate::{TlsConnector, TlsConnectorBuilder}; | use native_tls_crate::{TlsConnector, TlsConnectorBuilder}; | ||||||
| #[cfg(feature = "__tls")] | #[cfg(feature = "__tls")] | ||||||
| use http::header::HeaderValue; | use http::header::HeaderValue; | ||||||
|  | use futures_util::future::Either; | ||||||
| use bytes::{Buf, BufMut}; | use bytes::{Buf, BufMut}; | ||||||
|  |  | ||||||
| use std::future::Future; | use std::future::Future; | ||||||
| @@ -28,10 +29,80 @@ use self::native_tls_conn::NativeTlsConn; | |||||||
| #[cfg(feature = "rustls-tls")] | #[cfg(feature = "rustls-tls")] | ||||||
| use self::rustls_tls_conn::RustlsTlsConn; | use self::rustls_tls_conn::RustlsTlsConn; | ||||||
|  |  | ||||||
|  | #[derive(Clone)] | ||||||
|  | pub(crate) enum HttpConnector { | ||||||
|  |     Gai(hyper::client::HttpConnector), | ||||||
|     #[cfg(feature = "trust-dns")] |     #[cfg(feature = "trust-dns")] | ||||||
| type HttpConnector = hyper::client::HttpConnector<TrustDnsResolver>; |     TrustDns(hyper::client::HttpConnector<TrustDnsResolver>), | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl HttpConnector { | ||||||
|  |     pub(crate) fn new_gai() -> Self { | ||||||
|  |         Self::Gai(hyper::client::HttpConnector::new()) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[cfg(feature = "trust-dns")] | ||||||
|  |     pub(crate) fn new_trust_dns() -> crate::Result<HttpConnector> { | ||||||
|  |         TrustDnsResolver::new() | ||||||
|  |             .map(hyper::client::HttpConnector::new_with_resolver) | ||||||
|  |             .map(Self::TrustDns) | ||||||
|  |             .map_err(crate::error::builder) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | macro_rules! impl_http_connector { | ||||||
|  |     ($(fn $name:ident(&mut self, $($par_name:ident: $par_type:ty),*)$( -> $return:ty)?;)+) => { | ||||||
|  |         #[allow(dead_code)] | ||||||
|  |         impl HttpConnector { | ||||||
|  |             $( | ||||||
|  |                 fn $name(&mut self, $($par_name: $par_type),*)$( -> $return)? { | ||||||
|  |                     match self { | ||||||
|  |                         Self::Gai(resolver) => resolver.$name($($par_name),*), | ||||||
|  |                         #[cfg(feature = "trust-dns")] | ||||||
|  |                         Self::TrustDns(resolver) => resolver.$name($($par_name),*), | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             )+ | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl_http_connector! { | ||||||
|  |     fn set_local_address(&mut self, addr: Option<IpAddr>); | ||||||
|  |     fn enforce_http(&mut self, is_enforced: bool); | ||||||
|  |     fn set_nodelay(&mut self, nodelay: bool); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl Service<Uri> for HttpConnector { | ||||||
|  |     type Response = <hyper::client::HttpConnector as Service<Uri>>::Response; | ||||||
|  |     type Error = <hyper::client::HttpConnector as Service<Uri>>::Error; | ||||||
|  |     #[cfg(feature = "trust-dns")] | ||||||
|  |     type Future = Either< | ||||||
|  |         <hyper::client::HttpConnector as Service<Uri>>::Future, | ||||||
|  |         <hyper::client::HttpConnector<TrustDnsResolver> as Service<Uri>>::Future, | ||||||
|  |     >; | ||||||
|     #[cfg(not(feature = "trust-dns"))] |     #[cfg(not(feature = "trust-dns"))] | ||||||
| type HttpConnector = hyper::client::HttpConnector; |     type Future = Either< | ||||||
|  |         <hyper::client::HttpConnector as Service<Uri>>::Future, | ||||||
|  |         <hyper::client::HttpConnector as Service<Uri>>::Future, | ||||||
|  |     >; | ||||||
|  |  | ||||||
|  |     fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { | ||||||
|  |         match self { | ||||||
|  |             Self::Gai(resolver) => resolver.poll_ready(cx), | ||||||
|  |             #[cfg(feature = "trust-dns")] | ||||||
|  |             Self::TrustDns(resolver) => resolver.poll_ready(cx), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn call(&mut self, dst: Uri) -> Self::Future { | ||||||
|  |         match self { | ||||||
|  |             Self::Gai(resolver) => Either::Left(resolver.call(dst)), | ||||||
|  |             #[cfg(feature = "trust-dns")] | ||||||
|  |             Self::TrustDns(resolver) => Either::Right(resolver.call(dst)), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
| pub(crate) struct Connector { | pub(crate) struct Connector { | ||||||
| @@ -62,6 +133,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>( | ||||||
|  |         mut http: HttpConnector, | ||||||
|         proxies: Arc<Vec<Proxy>>, |         proxies: Arc<Vec<Proxy>>, | ||||||
|         local_addr: T, |         local_addr: T, | ||||||
|         nodelay: bool, |         nodelay: bool, | ||||||
| @@ -69,7 +141,6 @@ impl Connector { | |||||||
|     where |     where | ||||||
|         T: Into<Option<IpAddr>>, |         T: Into<Option<IpAddr>>, | ||||||
|     { |     { | ||||||
|         let mut http = http_connector()?; |  | ||||||
|         http.set_local_address(local_addr.into()); |         http.set_local_address(local_addr.into()); | ||||||
|         http.set_nodelay(nodelay); |         http.set_nodelay(nodelay); | ||||||
|         Ok(Connector { |         Ok(Connector { | ||||||
| @@ -82,6 +153,7 @@ impl Connector { | |||||||
|  |  | ||||||
|     #[cfg(feature = "default-tls")] |     #[cfg(feature = "default-tls")] | ||||||
|     pub(crate) fn new_default_tls<T>( |     pub(crate) fn new_default_tls<T>( | ||||||
|  |         http: HttpConnector, | ||||||
|         tls: TlsConnectorBuilder, |         tls: TlsConnectorBuilder, | ||||||
|         proxies: Arc<Vec<Proxy>>, |         proxies: Arc<Vec<Proxy>>, | ||||||
|         user_agent: Option<HeaderValue>, |         user_agent: Option<HeaderValue>, | ||||||
| @@ -93,6 +165,7 @@ impl Connector { | |||||||
|     { |     { | ||||||
|         let tls = tls.build().map_err(crate::error::builder)?; |         let tls = tls.build().map_err(crate::error::builder)?; | ||||||
|         Self::from_built_default_tls( |         Self::from_built_default_tls( | ||||||
|  |             http, | ||||||
|             tls, |             tls, | ||||||
|             proxies, |             proxies, | ||||||
|             user_agent, |             user_agent, | ||||||
| @@ -103,6 +176,7 @@ impl Connector { | |||||||
|  |  | ||||||
|     #[cfg(feature = "default-tls")] |     #[cfg(feature = "default-tls")] | ||||||
|     pub(crate) fn from_built_default_tls<T> ( |     pub(crate) fn from_built_default_tls<T> ( | ||||||
|  |         mut http: HttpConnector, | ||||||
|         tls: TlsConnector, |         tls: TlsConnector, | ||||||
|         proxies: Arc<Vec<Proxy>>, |         proxies: Arc<Vec<Proxy>>, | ||||||
|         user_agent: Option<HeaderValue>, |         user_agent: Option<HeaderValue>, | ||||||
| @@ -111,7 +185,6 @@ impl Connector { | |||||||
|         where |         where | ||||||
|             T: Into<Option<IpAddr>>, |             T: Into<Option<IpAddr>>, | ||||||
|     { |     { | ||||||
|         let mut http = http_connector()?; |  | ||||||
|         http.set_local_address(local_addr.into()); |         http.set_local_address(local_addr.into()); | ||||||
|         http.enforce_http(false); |         http.enforce_http(false); | ||||||
|  |  | ||||||
| @@ -127,6 +200,7 @@ impl Connector { | |||||||
|  |  | ||||||
|     #[cfg(feature = "rustls-tls")] |     #[cfg(feature = "rustls-tls")] | ||||||
|     pub(crate) fn new_rustls_tls<T>( |     pub(crate) fn new_rustls_tls<T>( | ||||||
|  |         mut http: HttpConnector, | ||||||
|         tls: rustls::ClientConfig, |         tls: rustls::ClientConfig, | ||||||
|         proxies: Arc<Vec<Proxy>>, |         proxies: Arc<Vec<Proxy>>, | ||||||
|         user_agent: Option<HeaderValue>, |         user_agent: Option<HeaderValue>, | ||||||
| @@ -136,7 +210,6 @@ impl Connector { | |||||||
|     where |     where | ||||||
|         T: Into<Option<IpAddr>>, |         T: Into<Option<IpAddr>>, | ||||||
|     { |     { | ||||||
|         let mut http = http_connector()?; |  | ||||||
|         http.set_local_address(local_addr.into()); |         http.set_local_address(local_addr.into()); | ||||||
|         http.enforce_http(false); |         http.enforce_http(false); | ||||||
|  |  | ||||||
| @@ -413,19 +486,6 @@ fn into_uri(scheme: Scheme, host: Authority) -> Uri { | |||||||
|         .expect("scheme and authority is valid Uri") |         .expect("scheme and authority is valid Uri") | ||||||
| } | } | ||||||
|  |  | ||||||
| #[cfg(feature = "trust-dns")] |  | ||||||
| fn http_connector() -> crate::Result<HttpConnector> { |  | ||||||
|     TrustDnsResolver::new() |  | ||||||
|         .map(HttpConnector::new_with_resolver) |  | ||||||
|         .map_err(crate::error::builder) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #[cfg(not(feature = "trust-dns"))] |  | ||||||
| fn http_connector() -> crate::Result<HttpConnector> { |  | ||||||
|     Ok(HttpConnector::new()) |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| async fn with_timeout<T, F>(f: F, timeout: Option<Duration>) -> Result<T, BoxError> | async fn with_timeout<T, F>(f: F, timeout: Option<Duration>) -> Result<T, BoxError> | ||||||
| where | where | ||||||
|     F: Future<Output = Result<T, BoxError>>, |     F: Future<Output = Result<T, BoxError>>, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user