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::response::Response; | ||||
| use super::Body; | ||||
| use crate::connect::Connector; | ||||
| use crate::connect::{Connector, HttpConnector}; | ||||
| #[cfg(feature = "cookies")] | ||||
| use crate::cookie; | ||||
| use crate::into_url::{expect_uri, try_uri}; | ||||
| @@ -91,6 +91,7 @@ struct Config { | ||||
|     nodelay: bool, | ||||
|     #[cfg(feature = "cookies")] | ||||
|     cookie_store: Option<cookie::CookieStore>, | ||||
|     trust_dns: bool, | ||||
|     error: Option<crate::Error>, | ||||
| } | ||||
|  | ||||
| @@ -138,6 +139,7 @@ impl ClientBuilder { | ||||
|                 http2_initial_connection_window_size: None, | ||||
|                 local_address: None, | ||||
|                 nodelay: false, | ||||
|                 trust_dns: cfg!(feature = "trust-dns"), | ||||
|                 #[cfg(feature = "cookies")] | ||||
|                 cookie_store: None, | ||||
|             }, | ||||
| @@ -169,6 +171,14 @@ impl ClientBuilder { | ||||
|                 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")] | ||||
|             match config.tls { | ||||
|                 #[cfg(feature = "default-tls")] | ||||
| @@ -195,6 +205,7 @@ impl ClientBuilder { | ||||
|  | ||||
|  | ||||
|                     Connector::new_default_tls( | ||||
|                         http, | ||||
|                         tls, | ||||
|                         proxies.clone(), | ||||
|                         user_agent(&config.headers), | ||||
| @@ -205,6 +216,7 @@ impl ClientBuilder { | ||||
|                 #[cfg(feature = "native-tls")] | ||||
|                 TlsBackend::BuiltNativeTls(conn) => { | ||||
|                     Connector::from_built_default_tls( | ||||
|                         http, | ||||
|                         conn, | ||||
|                         proxies.clone(), | ||||
|                         user_agent(&config.headers), | ||||
| @@ -214,6 +226,7 @@ impl ClientBuilder { | ||||
|                 #[cfg(feature = "rustls-tls")] | ||||
|                 TlsBackend::BuiltRustls(conn) => { | ||||
|                     Connector::new_rustls_tls( | ||||
|                         http, | ||||
|                         conn, | ||||
|                         proxies.clone(), | ||||
|                         user_agent(&config.headers), | ||||
| @@ -247,6 +260,7 @@ impl ClientBuilder { | ||||
|                     } | ||||
|  | ||||
|                     Connector::new_rustls_tls( | ||||
|                         http, | ||||
|                         tls, | ||||
|                         proxies.clone(), | ||||
|                         user_agent(&config.headers), | ||||
| @@ -266,7 +280,7 @@ impl ClientBuilder { | ||||
|             } | ||||
|  | ||||
|             #[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); | ||||
| @@ -793,6 +807,36 @@ impl ClientBuilder { | ||||
|         self.config.tls = crate::tls::TlsBackend::UnknownPreconfigured; | ||||
|         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>; | ||||
|   | ||||
| @@ -481,6 +481,27 @@ impl ClientBuilder { | ||||
|         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 | ||||
|  | ||||
|     fn with_inner<F>(mut self, func: F) -> ClientBuilder | ||||
|   | ||||
							
								
								
									
										100
									
								
								src/connect.rs
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								src/connect.rs
									
									
									
									
									
								
							| @@ -7,6 +7,7 @@ use tokio::io::{AsyncRead, AsyncWrite}; | ||||
| use native_tls_crate::{TlsConnector, TlsConnectorBuilder}; | ||||
| #[cfg(feature = "__tls")] | ||||
| use http::header::HeaderValue; | ||||
| use futures_util::future::Either; | ||||
| use bytes::{Buf, BufMut}; | ||||
|  | ||||
| use std::future::Future; | ||||
| @@ -28,10 +29,80 @@ use self::native_tls_conn::NativeTlsConn; | ||||
| #[cfg(feature = "rustls-tls")] | ||||
| use self::rustls_tls_conn::RustlsTlsConn; | ||||
|  | ||||
| #[cfg(feature = "trust-dns")] | ||||
| type HttpConnector = hyper::client::HttpConnector<TrustDnsResolver>; | ||||
| #[cfg(not(feature = "trust-dns"))] | ||||
| type HttpConnector = hyper::client::HttpConnector; | ||||
| #[derive(Clone)] | ||||
| pub(crate) enum HttpConnector { | ||||
|     Gai(hyper::client::HttpConnector), | ||||
|     #[cfg(feature = "trust-dns")] | ||||
|     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"))] | ||||
|     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)] | ||||
| pub(crate) struct Connector { | ||||
| @@ -62,6 +133,7 @@ enum Inner { | ||||
| impl Connector { | ||||
|     #[cfg(not(feature = "__tls"))] | ||||
|     pub(crate) fn new<T>( | ||||
|         mut http: HttpConnector, | ||||
|         proxies: Arc<Vec<Proxy>>, | ||||
|         local_addr: T, | ||||
|         nodelay: bool, | ||||
| @@ -69,7 +141,6 @@ impl Connector { | ||||
|     where | ||||
|         T: Into<Option<IpAddr>>, | ||||
|     { | ||||
|         let mut http = http_connector()?; | ||||
|         http.set_local_address(local_addr.into()); | ||||
|         http.set_nodelay(nodelay); | ||||
|         Ok(Connector { | ||||
| @@ -82,6 +153,7 @@ impl Connector { | ||||
|  | ||||
|     #[cfg(feature = "default-tls")] | ||||
|     pub(crate) fn new_default_tls<T>( | ||||
|         http: HttpConnector, | ||||
|         tls: TlsConnectorBuilder, | ||||
|         proxies: Arc<Vec<Proxy>>, | ||||
|         user_agent: Option<HeaderValue>, | ||||
| @@ -93,6 +165,7 @@ impl Connector { | ||||
|     { | ||||
|         let tls = tls.build().map_err(crate::error::builder)?; | ||||
|         Self::from_built_default_tls( | ||||
|             http, | ||||
|             tls, | ||||
|             proxies, | ||||
|             user_agent, | ||||
| @@ -103,6 +176,7 @@ impl Connector { | ||||
|  | ||||
|     #[cfg(feature = "default-tls")] | ||||
|     pub(crate) fn from_built_default_tls<T> ( | ||||
|         mut http: HttpConnector, | ||||
|         tls: TlsConnector, | ||||
|         proxies: Arc<Vec<Proxy>>, | ||||
|         user_agent: Option<HeaderValue>, | ||||
| @@ -111,7 +185,6 @@ impl Connector { | ||||
|         where | ||||
|             T: Into<Option<IpAddr>>, | ||||
|     { | ||||
|         let mut http = http_connector()?; | ||||
|         http.set_local_address(local_addr.into()); | ||||
|         http.enforce_http(false); | ||||
|  | ||||
| @@ -127,6 +200,7 @@ impl Connector { | ||||
|  | ||||
|     #[cfg(feature = "rustls-tls")] | ||||
|     pub(crate) fn new_rustls_tls<T>( | ||||
|         mut http: HttpConnector, | ||||
|         tls: rustls::ClientConfig, | ||||
|         proxies: Arc<Vec<Proxy>>, | ||||
|         user_agent: Option<HeaderValue>, | ||||
| @@ -136,7 +210,6 @@ impl Connector { | ||||
|     where | ||||
|         T: Into<Option<IpAddr>>, | ||||
|     { | ||||
|         let mut http = http_connector()?; | ||||
|         http.set_local_address(local_addr.into()); | ||||
|         http.enforce_http(false); | ||||
|  | ||||
| @@ -413,19 +486,6 @@ fn into_uri(scheme: Scheme, host: Authority) -> 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> | ||||
| where | ||||
|     F: Future<Output = Result<T, BoxError>>, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user