rework awc dns resolver

This commit is contained in:
fakeshadow 2021-01-19 12:00:18 +08:00
parent 0c8196f8b0
commit 9d4bc34473
8 changed files with 103 additions and 7 deletions

View File

@ -132,6 +132,8 @@ actix-multipart = { path = "actix-multipart" }
actix-files = { path = "actix-files" } actix-files = { path = "actix-files" }
awc = { path = "awc" } awc = { path = "awc" }
actix-tls = { git = "https://github.com/actix/actix-net", branch = "refactor/resolver" }
[[bench]] [[bench]]
name = "server" name = "server"
harness = false harness = false

View File

@ -106,7 +106,6 @@ pub async fn test_server_with_addr<F: ServiceFactory<TcpStream>>(
Client::builder().connector(connector).finish() Client::builder().connector(connector).finish()
}; };
actix_tls::connect::start_default_resolver().await.unwrap();
TestServer { TestServer {
addr, addr,

View File

@ -1,6 +1,5 @@
use std::io; use std::io;
use actix_tls::connect::resolver::ResolveError;
use derive_more::{Display, From}; use derive_more::{Display, From};
#[cfg(feature = "openssl")] #[cfg(feature = "openssl")]
@ -23,7 +22,7 @@ pub enum ConnectError {
/// Failed to resolve the hostname /// Failed to resolve the hostname
#[display(fmt = "Failed resolving hostname: {}", _0)] #[display(fmt = "Failed resolving hostname: {}", _0)]
Resolver(ResolveError), Resolver(Box<dyn std::error::Error>),
/// No dns records /// No dns records
#[display(fmt = "No dns records found for the input")] #[display(fmt = "No dns records found for the input")]

View File

@ -4,8 +4,12 @@
### Added ### Added
* `ClientRequest::insert_header` method which allows using typed headers. [#1869] * `ClientRequest::insert_header` method which allows using typed headers. [#1869]
* `ClientRequest::append_header` method which allows using typed headers. [#1869] * `ClientRequest::append_header` method which allows using typed headers. [#1869]
* `trust-dns` option feature to use it as default dns resolver.
* `connector::default_connector` function to get a default connector type
that uses current dns resolver feature.
### Removed ### Removed
* `trust-dns` removed from default dns resolver
* `ClientRequest::set`; use `ClientRequest::insert_header`. [#1869] * `ClientRequest::set`; use `ClientRequest::insert_header`. [#1869]
* `ClientRequest::set_header`; use `ClientRequest::insert_header`. [#1869] * `ClientRequest::set_header`; use `ClientRequest::insert_header`. [#1869]
* `ClientRequest::set_header_if_none`; use `ClientRequest::insert_header_if_none`. [#1869] * `ClientRequest::set_header_if_none`; use `ClientRequest::insert_header_if_none`. [#1869]

View File

@ -36,12 +36,18 @@ rustls = ["rust-tls", "actix-http/rustls"]
# content-encoding support # content-encoding support
compress = ["actix-http/compress"] compress = ["actix-http/compress"]
# trust-dns as dns resolver
trust-dns = ["trust-dns-resolver/tokio-runtime", "trust-dns-resolver/system-config"]
[dependencies] [dependencies]
actix-codec = "0.4.0-beta.1" actix-codec = "0.4.0-beta.1"
actix-service = "2.0.0-beta.3" actix-service = "2.0.0-beta.3"
actix-http = "3.0.0-beta.1" actix-http = "3.0.0-beta.1"
actix-rt = "2.0.0-beta.2" actix-rt = "2.0.0-beta.2"
# TODO: temporary import actix-tls to bypass some actix-http mods
actix-tls = { version = "3.0.0-beta.2", default-features = false, features = ["connect"] }
base64 = "0.13" base64 = "0.13"
bytes = "1" bytes = "1"
cfg-if = "1.0" cfg-if = "1.0"
@ -56,6 +62,7 @@ serde_json = "1.0"
serde_urlencoded = "0.7" serde_urlencoded = "0.7"
open-ssl = { version = "0.10", package = "openssl", optional = true } open-ssl = { version = "0.10", package = "openssl", optional = true }
rust-tls = { version = "0.19.0", package = "rustls", optional = true, features = ["dangerous_configuration"] } rust-tls = { version = "0.19.0", package = "rustls", optional = true, features = ["dangerous_configuration"] }
trust-dns-resolver = { version = "0.20.0", default-features = false, optional = true }
[dev-dependencies] [dev-dependencies]
# TODO: actix is temporary added as dev dep for actix-macro reason. # TODO: actix is temporary added as dev dep for actix-macro reason.

84
awc/src/connector.rs Normal file
View File

@ -0,0 +1,84 @@
// TODO: this mod bypass actix-http and use actix_tls::connect directly.
// Future refactor should change this mod if actix-http still used as upstream dep of awc.
pub(crate) use connector_impl::*;
#[cfg(not(features = "trust-dns"))]
pub(crate) mod connector_impl {
pub(crate) use actix_tls::connect::default_connector;
}
#[cfg(features = "trust-dns")]
pub(crate) mod connector_impl {
// resolver implementation using trust-dns crate.
use std::net::SocketAddr;
use actix_rt::{net::TcpStream, Arbiter};
use actix_service::ServiceFactory;
use actix_tls::connect::{Connect, ConnectError, Connection, Resolve, Resolver};
use futures_core::future::LocalBoxFuture;
use trust_dns_resolver::{
config::{ResolverConfig, ResolverOpts},
system_conf::read_system_conf,
TokioAsyncResolver,
};
pub struct TrustDnsResolver {
resolver: TokioAsyncResolver,
}
impl TrustDnsResolver {
fn new() -> Self {
// dns struct is cached in Arbiter thread local map.
// so new client constructor can reuse the dns resolver on local thread.
if Arbiter::contains_item::<TokioAsyncResolver>() {
Arbiter::get_item(|item: &TokioAsyncResolver| TrustDnsResolver {
resolver: item.clone(),
})
} else {
let (cfg, opts) = match read_system_conf() {
Ok((cfg, opts)) => (cfg, opts),
Err(e) => {
log::error!("TRust-DNS can not load system config: {}", e);
(ResolverConfig::default(), ResolverOpts::default())
}
};
let resolver = TokioAsyncResolver::tokio(cfg, opts).unwrap();
Arbiter::set_item(resolver.clone());
resolver
}
}
}
impl Resolve for TrustDnsResolver {
fn lookup<'a>(
&'a self,
host: &'a str,
port: u16,
) -> LocalBoxFuture<'a, Result<Vec<SocketAddr>, Box<dyn std::error::Error>>>
{
Box::pin(async move {
let res = self
.trust_dns
.lookup_ip(host)
.await?
.iter()
.map(|ip| SocketAddr::new(ip, port))
.collect();
Ok(res)
})
}
}
pub(crate) fn default_connector() -> impl ServiceFactory<
Connect<T>,
Config = (),
Response = Connection<T, TcpStream>,
Error = ConnectError,
InitError = (),
> + Clone {
actix_tls::connect::new_connector(Resolver::new_custom(TrustDnsResolver::new()))
}
}

View File

@ -105,6 +105,7 @@ use actix_http::RequestHead;
mod builder; mod builder;
mod connect; mod connect;
mod connector;
pub mod error; pub mod error;
mod frozen; mod frozen;
mod request; mod request;
@ -154,7 +155,9 @@ impl Default for Client {
fn default() -> Self { fn default() -> Self {
Client(Rc::new(ClientConfig { Client(Rc::new(ClientConfig {
connector: RefCell::new(Box::new(ConnectorWrapper( connector: RefCell::new(Box::new(ConnectorWrapper(
Connector::new().finish(), Connector::new()
.connector(connector::default_connector())
.finish(),
))), ))),
headers: HeaderMap::new(), headers: HeaderMap::new(),
timeout: Some(Duration::from_secs(5)), timeout: Some(Duration::from_secs(5)),

View File

@ -120,9 +120,7 @@ async fn test_timeout() {
}); });
let connector = awc::Connector::new() let connector = awc::Connector::new()
.connector(actix_tls::connect::new_connector( .connector(actix_tls::connect::default_connector())
actix_tls::connect::start_default_resolver().await.unwrap(),
))
.timeout(Duration::from_secs(15)) .timeout(Duration::from_secs(15))
.finish(); .finish();