Replace getaddrinfo resolver with trust-dns-resolver

This commit is contained in:
Sean McArthur
2018-12-17 13:28:15 -08:00
parent b259d7c5f3
commit 44837c1b69
6 changed files with 98 additions and 22 deletions

View File

@@ -27,7 +27,10 @@ serde = "1.0"
serde_json = "1.0"
serde_urlencoded = "0.5"
tokio = "0.1.7"
tokio-executor = "0.1.4" # a minimum version so trust-dns-resolver compiles
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"
uuid = { version = "0.7", features = ["v4"] }
hyper-rustls = { version = "0.15", optional = true }

View File

@@ -60,7 +60,6 @@ struct Config {
identity: Option<Identity>,
#[cfg(feature = "tls")]
tls: TLSBackend,
dns_threads: usize,
}
impl ClientBuilder {
@@ -88,7 +87,6 @@ impl ClientBuilder {
identity: None,
#[cfg(feature = "tls")]
tls: TLSBackend::default(),
dns_threads: 4,
},
}
}
@@ -131,7 +129,7 @@ impl ClientBuilder {
tls.identity(id);
}
Connector::new_default_tls(config.dns_threads, tls, proxies.clone())?
Connector::new_default_tls(tls, proxies.clone())?
},
#[cfg(feature = "rustls-tls")]
TLSBackend::Rustls => {
@@ -188,12 +186,12 @@ impl ClientBuilder {
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"))]
Connector::new(config.dns_threads, proxies.clone())
Connector::new(proxies.clone())
};
let hyper_client = ::hyper::Client::builder()
@@ -327,9 +325,9 @@ impl ClientBuilder {
self
}
/// Set number of DNS threads.
pub fn dns_threads(mut self, threads: usize) -> ClientBuilder {
self.config.dns_threads = threads;
#[doc(hidden)]
#[deprecated(note = "DNS no longer uses blocking threads")]
pub fn dns_threads(self, _threads: usize) -> ClientBuilder {
self
}
}

View File

@@ -281,13 +281,6 @@ impl ClientBuilder {
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
where
F: FnOnce(async_impl::ClientBuilder) -> async_impl::ClientBuilder,

View File

@@ -1,6 +1,5 @@
use futures::Future;
use http::uri::Scheme;
use hyper::client::{HttpConnector};
use hyper::client::connect::{Connect, Connected, Destination};
use tokio_io::{AsyncRead, AsyncWrite};
@@ -14,8 +13,11 @@ use bytes::BufMut;
use std::io;
use std::sync::Arc;
use dns::TrustDnsResolver;
use Proxy;
type HttpConnector = ::hyper::client::HttpConnector<TrustDnsResolver>;
pub(crate) struct Connector {
proxies: Arc<Vec<Proxy>>,
@@ -33,8 +35,8 @@ enum Inner {
impl Connector {
#[cfg(not(feature = "tls"))]
pub(crate) fn new(threads: usize, proxies: Arc<Vec<Proxy>>) -> Connector {
let http = HttpConnector::new(threads);
pub(crate) fn new(proxies: Arc<Vec<Proxy>>) -> Connector {
let http = http_connector();
Connector {
proxies,
inner: Inner::Http(http)
@@ -42,10 +44,10 @@ impl Connector {
}
#[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 mut http = HttpConnector::new(threads);
let mut http = http_connector();
http.enforce_http(false);
let http = ::hyper_tls::HttpsConnector::from((http, tls.clone()));
@@ -56,8 +58,8 @@ impl Connector {
}
#[cfg(feature = "rustls-tls")]
pub(crate) fn new_rustls_tls(threads: usize, tls: rustls::ClientConfig, proxies: Arc<Vec<Proxy>>) -> ::Result<Connector> {
let mut http = HttpConnector::new(threads);
pub(crate) fn new_rustls_tls(tls: rustls::ClientConfig, proxies: Arc<Vec<Proxy>>) -> ::Result<Connector> {
let mut http = http_connector();
http.enforce_http(false);
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 {
type Transport = Conn;
type Error = io::Error;

73
src/dns.rs Normal file
View 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())
}))
}))
}
}

View File

@@ -163,6 +163,7 @@ extern crate serde_urlencoded;
extern crate tokio;
#[cfg_attr(feature = "default-tls", macro_use)]
extern crate tokio_io;
extern crate trust_dns_resolver;
extern crate url;
extern crate uuid;
@@ -203,6 +204,7 @@ mod connect;
mod connect_async;
mod body;
mod client;
mod dns;
mod into_url;
mod proxy;
mod redirect;