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
|
||||||
|
|||||||
100
src/connect.rs
100
src/connect.rs
@@ -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;
|
||||||
|
|
||||||
#[cfg(feature = "trust-dns")]
|
#[derive(Clone)]
|
||||||
type HttpConnector = hyper::client::HttpConnector<TrustDnsResolver>;
|
pub(crate) enum HttpConnector {
|
||||||
#[cfg(not(feature = "trust-dns"))]
|
Gai(hyper::client::HttpConnector),
|
||||||
type HttpConnector = 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)]
|
#[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