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