mirror of https://github.com/fafhrd91/actix-web
rework awc dns resolver
This commit is contained in:
parent
0c8196f8b0
commit
9d4bc34473
|
@ -132,6 +132,8 @@ actix-multipart = { path = "actix-multipart" }
|
|||
actix-files = { path = "actix-files" }
|
||||
awc = { path = "awc" }
|
||||
|
||||
actix-tls = { git = "https://github.com/actix/actix-net", branch = "refactor/resolver" }
|
||||
|
||||
[[bench]]
|
||||
name = "server"
|
||||
harness = false
|
||||
|
|
|
@ -106,7 +106,6 @@ pub async fn test_server_with_addr<F: ServiceFactory<TcpStream>>(
|
|||
|
||||
Client::builder().connector(connector).finish()
|
||||
};
|
||||
actix_tls::connect::start_default_resolver().await.unwrap();
|
||||
|
||||
TestServer {
|
||||
addr,
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::io;
|
||||
|
||||
use actix_tls::connect::resolver::ResolveError;
|
||||
use derive_more::{Display, From};
|
||||
|
||||
#[cfg(feature = "openssl")]
|
||||
|
@ -23,7 +22,7 @@ pub enum ConnectError {
|
|||
|
||||
/// Failed to resolve the hostname
|
||||
#[display(fmt = "Failed resolving hostname: {}", _0)]
|
||||
Resolver(ResolveError),
|
||||
Resolver(Box<dyn std::error::Error>),
|
||||
|
||||
/// No dns records
|
||||
#[display(fmt = "No dns records found for the input")]
|
||||
|
|
|
@ -4,8 +4,12 @@
|
|||
### Added
|
||||
* `ClientRequest::insert_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
|
||||
* `trust-dns` removed from default dns resolver
|
||||
* `ClientRequest::set`; 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]
|
||||
|
|
|
@ -36,12 +36,18 @@ rustls = ["rust-tls", "actix-http/rustls"]
|
|||
# content-encoding support
|
||||
compress = ["actix-http/compress"]
|
||||
|
||||
# trust-dns as dns resolver
|
||||
trust-dns = ["trust-dns-resolver/tokio-runtime", "trust-dns-resolver/system-config"]
|
||||
|
||||
[dependencies]
|
||||
actix-codec = "0.4.0-beta.1"
|
||||
actix-service = "2.0.0-beta.3"
|
||||
actix-http = "3.0.0-beta.1"
|
||||
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"
|
||||
bytes = "1"
|
||||
cfg-if = "1.0"
|
||||
|
@ -56,6 +62,7 @@ serde_json = "1.0"
|
|||
serde_urlencoded = "0.7"
|
||||
open-ssl = { version = "0.10", package = "openssl", optional = true }
|
||||
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]
|
||||
# TODO: actix is temporary added as dev dep for actix-macro reason.
|
||||
|
|
|
@ -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()))
|
||||
}
|
||||
}
|
|
@ -105,6 +105,7 @@ use actix_http::RequestHead;
|
|||
|
||||
mod builder;
|
||||
mod connect;
|
||||
mod connector;
|
||||
pub mod error;
|
||||
mod frozen;
|
||||
mod request;
|
||||
|
@ -154,7 +155,9 @@ impl Default for Client {
|
|||
fn default() -> Self {
|
||||
Client(Rc::new(ClientConfig {
|
||||
connector: RefCell::new(Box::new(ConnectorWrapper(
|
||||
Connector::new().finish(),
|
||||
Connector::new()
|
||||
.connector(connector::default_connector())
|
||||
.finish(),
|
||||
))),
|
||||
headers: HeaderMap::new(),
|
||||
timeout: Some(Duration::from_secs(5)),
|
||||
|
|
|
@ -120,9 +120,7 @@ async fn test_timeout() {
|
|||
});
|
||||
|
||||
let connector = awc::Connector::new()
|
||||
.connector(actix_tls::connect::new_connector(
|
||||
actix_tls::connect::start_default_resolver().await.unwrap(),
|
||||
))
|
||||
.connector(actix_tls::connect::default_connector())
|
||||
.timeout(Duration::from_secs(15))
|
||||
.finish();
|
||||
|
||||
|
|
Loading…
Reference in New Issue