Replace getaddrinfo resolver with trust-dns-resolver
This commit is contained in:
@@ -27,7 +27,10 @@ serde = "1.0"
|
|||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde_urlencoded = "0.5"
|
serde_urlencoded = "0.5"
|
||||||
tokio = "0.1.7"
|
tokio = "0.1.7"
|
||||||
|
tokio-executor = "0.1.4" # a minimum version so trust-dns-resolver compiles
|
||||||
tokio-io = "0.1"
|
tokio-io = "0.1"
|
||||||
|
tokio-timer = "0.2.6" # a minimum version so trust-dns-resolver compiles
|
||||||
|
trust-dns-resolver = "0.10"
|
||||||
url = "1.2"
|
url = "1.2"
|
||||||
uuid = { version = "0.7", features = ["v4"] }
|
uuid = { version = "0.7", features = ["v4"] }
|
||||||
hyper-rustls = { version = "0.15", optional = true }
|
hyper-rustls = { version = "0.15", optional = true }
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ struct Config {
|
|||||||
identity: Option<Identity>,
|
identity: Option<Identity>,
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
tls: TLSBackend,
|
tls: TLSBackend,
|
||||||
dns_threads: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientBuilder {
|
impl ClientBuilder {
|
||||||
@@ -88,7 +87,6 @@ impl ClientBuilder {
|
|||||||
identity: None,
|
identity: None,
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
tls: TLSBackend::default(),
|
tls: TLSBackend::default(),
|
||||||
dns_threads: 4,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,7 +129,7 @@ impl ClientBuilder {
|
|||||||
tls.identity(id);
|
tls.identity(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Connector::new_default_tls(config.dns_threads, tls, proxies.clone())?
|
Connector::new_default_tls(tls, proxies.clone())?
|
||||||
},
|
},
|
||||||
#[cfg(feature = "rustls-tls")]
|
#[cfg(feature = "rustls-tls")]
|
||||||
TLSBackend::Rustls => {
|
TLSBackend::Rustls => {
|
||||||
@@ -188,12 +186,12 @@ impl ClientBuilder {
|
|||||||
tls.set_single_client_cert(certs, key);
|
tls.set_single_client_cert(certs, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
Connector::new_rustls_tls(config.dns_threads, tls, proxies.clone())?
|
Connector::new_rustls_tls(tls, proxies.clone())?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "tls"))]
|
#[cfg(not(feature = "tls"))]
|
||||||
Connector::new(config.dns_threads, proxies.clone())
|
Connector::new(proxies.clone())
|
||||||
};
|
};
|
||||||
|
|
||||||
let hyper_client = ::hyper::Client::builder()
|
let hyper_client = ::hyper::Client::builder()
|
||||||
@@ -327,9 +325,9 @@ impl ClientBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set number of DNS threads.
|
#[doc(hidden)]
|
||||||
pub fn dns_threads(mut self, threads: usize) -> ClientBuilder {
|
#[deprecated(note = "DNS no longer uses blocking threads")]
|
||||||
self.config.dns_threads = threads;
|
pub fn dns_threads(self, _threads: usize) -> ClientBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -281,13 +281,6 @@ impl ClientBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the number of threads to use for DNS
|
|
||||||
///
|
|
||||||
/// Default is 4
|
|
||||||
pub fn dns_threads(self, threads: usize) -> ClientBuilder {
|
|
||||||
self.with_inner(|inner| inner.dns_threads(threads))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_inner<F>(mut self, func: F) -> ClientBuilder
|
fn with_inner<F>(mut self, func: F) -> ClientBuilder
|
||||||
where
|
where
|
||||||
F: FnOnce(async_impl::ClientBuilder) -> async_impl::ClientBuilder,
|
F: FnOnce(async_impl::ClientBuilder) -> async_impl::ClientBuilder,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use futures::Future;
|
use futures::Future;
|
||||||
use http::uri::Scheme;
|
use http::uri::Scheme;
|
||||||
use hyper::client::{HttpConnector};
|
|
||||||
use hyper::client::connect::{Connect, Connected, Destination};
|
use hyper::client::connect::{Connect, Connected, Destination};
|
||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
|
|
||||||
@@ -14,8 +13,11 @@ use bytes::BufMut;
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use dns::TrustDnsResolver;
|
||||||
use Proxy;
|
use Proxy;
|
||||||
|
|
||||||
|
type HttpConnector = ::hyper::client::HttpConnector<TrustDnsResolver>;
|
||||||
|
|
||||||
|
|
||||||
pub(crate) struct Connector {
|
pub(crate) struct Connector {
|
||||||
proxies: Arc<Vec<Proxy>>,
|
proxies: Arc<Vec<Proxy>>,
|
||||||
@@ -33,8 +35,8 @@ enum Inner {
|
|||||||
|
|
||||||
impl Connector {
|
impl Connector {
|
||||||
#[cfg(not(feature = "tls"))]
|
#[cfg(not(feature = "tls"))]
|
||||||
pub(crate) fn new(threads: usize, proxies: Arc<Vec<Proxy>>) -> Connector {
|
pub(crate) fn new(proxies: Arc<Vec<Proxy>>) -> Connector {
|
||||||
let http = HttpConnector::new(threads);
|
let http = http_connector();
|
||||||
Connector {
|
Connector {
|
||||||
proxies,
|
proxies,
|
||||||
inner: Inner::Http(http)
|
inner: Inner::Http(http)
|
||||||
@@ -42,10 +44,10 @@ impl Connector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "default-tls")]
|
#[cfg(feature = "default-tls")]
|
||||||
pub(crate) fn new_default_tls(threads: usize, tls: TlsConnectorBuilder, proxies: Arc<Vec<Proxy>>) -> ::Result<Connector> {
|
pub(crate) fn new_default_tls(tls: TlsConnectorBuilder, proxies: Arc<Vec<Proxy>>) -> ::Result<Connector> {
|
||||||
let tls = try_!(tls.build());
|
let tls = try_!(tls.build());
|
||||||
|
|
||||||
let mut http = HttpConnector::new(threads);
|
let mut http = http_connector();
|
||||||
http.enforce_http(false);
|
http.enforce_http(false);
|
||||||
let http = ::hyper_tls::HttpsConnector::from((http, tls.clone()));
|
let http = ::hyper_tls::HttpsConnector::from((http, tls.clone()));
|
||||||
|
|
||||||
@@ -56,8 +58,8 @@ impl Connector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "rustls-tls")]
|
#[cfg(feature = "rustls-tls")]
|
||||||
pub(crate) fn new_rustls_tls(threads: usize, tls: rustls::ClientConfig, proxies: Arc<Vec<Proxy>>) -> ::Result<Connector> {
|
pub(crate) fn new_rustls_tls(tls: rustls::ClientConfig, proxies: Arc<Vec<Proxy>>) -> ::Result<Connector> {
|
||||||
let mut http = HttpConnector::new(threads);
|
let mut http = http_connector();
|
||||||
http.enforce_http(false);
|
http.enforce_http(false);
|
||||||
let http = ::hyper_rustls::HttpsConnector::from((http, tls.clone()));
|
let http = ::hyper_rustls::HttpsConnector::from((http, tls.clone()));
|
||||||
|
|
||||||
@@ -68,6 +70,11 @@ impl Connector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn http_connector() -> HttpConnector {
|
||||||
|
let http = HttpConnector::new_with_resolver(TrustDnsResolver::new());
|
||||||
|
http
|
||||||
|
}
|
||||||
|
|
||||||
impl Connect for Connector {
|
impl Connect for Connector {
|
||||||
type Transport = Conn;
|
type Transport = Conn;
|
||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
|
|||||||
73
src/dns.rs
Normal file
73
src/dns.rs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
use std::io;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
use futures::{future, Future};
|
||||||
|
use hyper::client::connect::dns as hyper_dns;
|
||||||
|
use trust_dns_resolver::AsyncResolver;
|
||||||
|
|
||||||
|
// If instead the type were just `AsyncResolver`, it breaks the default recursion limit
|
||||||
|
// for the compiler to determine if `reqwest::Client` is `Send`. This is because `AsyncResolver`
|
||||||
|
// has **a lot** of internal generic types that pushes us over the limit.
|
||||||
|
//
|
||||||
|
// "Erasing" the internal resolver type saves us from this limit.
|
||||||
|
type ErasedResolver = Box<Fn(hyper_dns::Name) -> ::trust_dns_resolver::BackgroundLookupIp + Send + Sync>;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub(crate) struct TrustDnsResolver {
|
||||||
|
inner: Arc<Mutex<Option<ErasedResolver>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TrustDnsResolver {
|
||||||
|
pub(crate) fn new() -> Self {
|
||||||
|
TrustDnsResolver {
|
||||||
|
inner: Arc::new(Mutex::new(None)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl hyper_dns::Resolve for TrustDnsResolver {
|
||||||
|
type Addrs = ::std::vec::IntoIter<::std::net::IpAddr>;
|
||||||
|
type Future = Box<Future<Item=Self::Addrs, Error=io::Error> + Send>;
|
||||||
|
|
||||||
|
fn resolve(&self, name: hyper_dns::Name) -> Self::Future {
|
||||||
|
let inner = self.inner.clone();
|
||||||
|
Box::new(future::lazy(move || {
|
||||||
|
let mut inner = inner.lock().expect("lock resolver");
|
||||||
|
if inner.is_none() {
|
||||||
|
// The `bg` (background) future needs to be spawned onto an executor,
|
||||||
|
// but a `reqwest::Client` may be constructed before an executor is ready.
|
||||||
|
// So, the `bg` future cannot be spawned *until* the executor starts to
|
||||||
|
// `poll` this future.
|
||||||
|
match AsyncResolver::from_system_conf() {
|
||||||
|
Ok((resolver, bg)) => {
|
||||||
|
::tokio::spawn(bg);
|
||||||
|
*inner = Some(Box::new(move |name| {
|
||||||
|
resolver.lookup_ip(name.as_str())
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
return future::Either::A(
|
||||||
|
future::err(io::Error::new(io::ErrorKind::Other, err.to_string()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
future::Either::B((inner
|
||||||
|
.as_mut()
|
||||||
|
.expect("resolver is set"))(name)
|
||||||
|
//.lookup_ip(name.as_str())
|
||||||
|
.map(|lookup| {
|
||||||
|
lookup
|
||||||
|
.iter()
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into_iter()
|
||||||
|
})
|
||||||
|
.map_err(|err| {
|
||||||
|
io::Error::new(io::ErrorKind::Other, err.to_string())
|
||||||
|
}))
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -163,6 +163,7 @@ extern crate serde_urlencoded;
|
|||||||
extern crate tokio;
|
extern crate tokio;
|
||||||
#[cfg_attr(feature = "default-tls", macro_use)]
|
#[cfg_attr(feature = "default-tls", macro_use)]
|
||||||
extern crate tokio_io;
|
extern crate tokio_io;
|
||||||
|
extern crate trust_dns_resolver;
|
||||||
extern crate url;
|
extern crate url;
|
||||||
extern crate uuid;
|
extern crate uuid;
|
||||||
|
|
||||||
@@ -203,6 +204,7 @@ mod connect;
|
|||||||
mod connect_async;
|
mod connect_async;
|
||||||
mod body;
|
mod body;
|
||||||
mod client;
|
mod client;
|
||||||
|
mod dns;
|
||||||
mod into_url;
|
mod into_url;
|
||||||
mod proxy;
|
mod proxy;
|
||||||
mod redirect;
|
mod redirect;
|
||||||
|
|||||||
Reference in New Issue
Block a user