diff --git a/ntex-router/CHANGES.txt b/ntex-router/CHANGES.txt index 70ce86cc..b1318e95 100644 --- a/ntex-router/CHANGES.txt +++ b/ntex-router/CHANGES.txt @@ -1,5 +1,9 @@ # Changes +## [0.4.3] - 2021-04-03 + +* Disable some of regex features + ## [0.4.2] - 2021-03-16 * Use `IntoPattern` for prefix resources diff --git a/ntex-router/Cargo.toml b/ntex-router/Cargo.toml index 4b68fd26..7168659d 100644 --- a/ntex-router/Cargo.toml +++ b/ntex-router/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ntex-router" -version = "0.4.2" +version = "0.4.3" authors = ["ntex contributors "] description = "Path router" keywords = ["ntex"] @@ -17,11 +17,11 @@ path = "src/lib.rs" default = ["http"] [dependencies] -regex = "1.4" serde = "1.0" bytestring = "1.0" log = "0.4" http = { version = "0.2", optional = true } +regex = { version = "1.4.5", default-features = false, features = ["std"] } [dev-dependencies] http = "0.2" diff --git a/ntex/CHANGES.md b/ntex/CHANGES.md index 7c42d0e8..d301935b 100644 --- a/ntex/CHANGES.md +++ b/ntex/CHANGES.md @@ -6,6 +6,8 @@ * util: add custom Ready, Either future and several helper functions +* drop trust-dns, use blocking calls + * reduce futures crate dependencies ## [0.3.13] - 2021-03-26 diff --git a/ntex/Cargo.toml b/ntex/Cargo.toml index 199b24d6..49100d0c 100644 --- a/ntex/Cargo.toml +++ b/ntex/Cargo.toml @@ -62,7 +62,7 @@ num_cpus = "1.13" nanorand = "0.5" percent-encoding = "2.1" pin-project-lite = "0.2" -regex = "1.4" +regex = { version = "1.4.5", default-features = false, features = ["std"] } sha-1 = "0.9" slab = "0.4" serde = { version = "1.0", features=["derive"] } @@ -73,10 +73,6 @@ url = "2.1" coo-kie = { version = "0.15", package = "cookie", optional = true } tokio = { version = "1", default-features=false, features = ["sync"] } -# resolver -trust-dns-proto = { version = "0.20", default-features = false } -trust-dns-resolver = { version = "0.20", default-features = false, features=["system-config", "tokio-runtime"] } - # openssl open-ssl = { version="0.10", package = "openssl", optional = true } tokio-openssl = { version = "0.6.1", optional = true } diff --git a/ntex/src/connect/error.rs b/ntex/src/connect/error.rs index 3c56f072..5f8a11f6 100644 --- a/ntex/src/connect/error.rs +++ b/ntex/src/connect/error.rs @@ -1,13 +1,13 @@ use std::io; use derive_more::{Display, From}; -use trust_dns_resolver::error::ResolveError; #[derive(Debug, From, Display)] pub enum ConnectError { /// Failed to resolve the hostname + #[from(ignore)] #[display(fmt = "Failed resolving hostname: {}", _0)] - Resolver(ResolveError), + Resolver(io::Error), /// No dns records #[display(fmt = "No dns records found for the input")] diff --git a/ntex/src/connect/mod.rs b/ntex/src/connect/mod.rs index 2c8671b0..da399085 100644 --- a/ntex/src/connect/mod.rs +++ b/ntex/src/connect/mod.rs @@ -13,42 +13,13 @@ pub mod openssl; #[cfg(feature = "rustls")] pub mod rustls; -pub use trust_dns_resolver::config::{self, ResolverConfig, ResolverOpts}; -use trust_dns_resolver::system_conf::read_system_conf; -pub use trust_dns_resolver::{error::ResolveError, TokioAsyncResolver as DnsResolver}; - -use crate::rt::{net::TcpStream, Arbiter}; +use crate::rt::net::TcpStream; pub use self::error::ConnectError; pub use self::message::{Address, Connect}; pub use self::resolve::Resolver; pub use self::service::Connector; -pub fn start_resolver(cfg: ResolverConfig, opts: ResolverOpts) -> DnsResolver { - DnsResolver::tokio(cfg, opts).unwrap() -} - -struct DefaultResolver(DnsResolver); - -pub fn default_resolver() -> DnsResolver { - if Arbiter::contains_item::() { - Arbiter::get_item(|item: &DefaultResolver| item.0.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 = DnsResolver::tokio(cfg, opts).unwrap(); - - Arbiter::set_item(DefaultResolver(resolver.clone())); - resolver - } -} - /// Resolve and connect to remote host pub fn connect(message: U) -> impl Future> where @@ -56,6 +27,6 @@ where Connect: From, { service::ConnectServiceResponse::new(Box::pin( - Resolver::new(default_resolver()).lookup(message.into()), + Resolver::new().lookup(message.into()), )) } diff --git a/ntex/src/connect/openssl.rs b/ntex/src/connect/openssl.rs index 2d472181..327041c7 100644 --- a/ntex/src/connect/openssl.rs +++ b/ntex/src/connect/openssl.rs @@ -7,7 +7,7 @@ use crate::rt::net::TcpStream; use crate::service::{Service, ServiceFactory}; use crate::util::Ready; -use super::{Address, Connect, ConnectError, Connector, DnsResolver}; +use super::{Address, Connect, ConnectError, Connector}; pub struct OpensslConnector { connector: Connector, @@ -22,14 +22,6 @@ impl OpensslConnector { openssl: connector, } } - - /// Construct new connect service with custom dns resolver - pub fn with_resolver(connector: SslConnector, resolver: DnsResolver) -> Self { - OpensslConnector { - connector: Connector::new(resolver), - openssl: connector, - } - } } impl OpensslConnector { diff --git a/ntex/src/connect/resolve.rs b/ntex/src/connect/resolve.rs index d545f32e..d4b50508 100644 --- a/ntex/src/connect/resolve.rs +++ b/ntex/src/connect/resolve.rs @@ -1,33 +1,22 @@ -use std::{ - fmt, future::Future, marker::PhantomData, net::SocketAddr, pin::Pin, rc::Rc, - task::Context, task::Poll, -}; +use std::{fmt, future::Future, io, marker, net, pin::Pin, task::Context, task::Poll}; -use super::{default_resolver, Address, Connect, ConnectError, DnsResolver}; +use super::{Address, Connect, ConnectError}; use crate::service::{Service, ServiceFactory}; use crate::util::{Either, Ready}; /// DNS Resolver Service -pub struct Resolver { - resolver: Rc, - _t: PhantomData, -} +pub struct Resolver(marker::PhantomData); impl fmt::Debug for Resolver { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Resolver") - .field("resolver", &self.resolver) - .finish() + f.debug_struct("Resolver").finish() } } impl Resolver { /// Create new resolver instance with custom configuration and options. - pub fn new(resolver: DnsResolver) -> Self { - Resolver { - resolver: Rc::new(resolver), - _t: PhantomData, - } + pub fn new() -> Self { + Resolver(marker::PhantomData) } } @@ -40,24 +29,29 @@ impl Resolver { if req.addr.is_some() || req.req.addr().is_some() { Either::Right(Ready::ok(req)) } else if let Ok(ip) = req.host().parse() { - req.addr = Some(Either::Left(SocketAddr::new(ip, req.port()))); + req.addr = Some(Either::Left(net::SocketAddr::new(ip, req.port()))); Either::Right(Ready::ok(req)) } else { trace!("DNS resolver: resolving host {:?}", req.host()); - let resolver = self.resolver.clone(); Either::Left(async move { - let fut = if let Some(host) = req.host().splitn(2, ':').next() { - resolver.lookup_ip(host) + let host = if req.host().contains(':') { + req.host().to_string() } else { - resolver.lookup_ip(req.host()) + format!("{}:{}", req.host(), req.port()) }; + let fut = crate::rt::task::spawn_blocking(move || { + net::ToSocketAddrs::to_socket_addrs(&host) + }); + match fut.await { - Ok(ips) => { + Ok(Ok(ips)) => { let port = req.port(); - let req = req - .set_addrs(ips.iter().map(|ip| SocketAddr::new(ip, port))); + let req = req.set_addrs(ips.map(|mut ip| { + ip.set_port(port); + ip + })); trace!( "DNS resolver: host {:?} resolved to {:?}", @@ -71,13 +65,24 @@ impl Resolver { Ok(req) } } + Ok(Err(e)) => { + trace!( + "DNS resolver: failed to resolve host {:?} err: {}", + req.host(), + e + ); + Err(ConnectError::Resolver(e)) + } Err(e) => { trace!( "DNS resolver: failed to resolve host {:?} err: {}", req.host(), e ); - Err(e.into()) + Err(ConnectError::Resolver(io::Error::new( + io::ErrorKind::Other, + e, + ))) } } }) @@ -87,19 +92,13 @@ impl Resolver { impl Default for Resolver { fn default() -> Resolver { - Resolver { - resolver: Rc::new(default_resolver()), - _t: PhantomData, - } + Resolver(marker::PhantomData) } } impl Clone for Resolver { fn clone(&self) -> Self { - Resolver { - resolver: self.resolver.clone(), - _t: PhantomData, - } + Resolver(marker::PhantomData) } } @@ -141,7 +140,7 @@ mod tests { #[crate::rt_test] async fn resolver() { - let resolver = Resolver::new(DnsResolver::tokio_from_system_conf().unwrap()); + let resolver = Resolver::new(); assert!(format!("{:?}", resolver).contains("Resolver")); let srv = resolver.new_service(()).await.unwrap(); assert!(lazy(|cx| srv.poll_ready(cx)).await.is_ready()); @@ -152,7 +151,7 @@ mod tests { let res = srv.call(Connect::new("---11213")).await; assert!(res.is_err()); - let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap(); + let addr: net::SocketAddr = "127.0.0.1:8080".parse().unwrap(); let res = srv .call(Connect::new("www.rust-lang.org").set_addrs(vec![addr])) .await diff --git a/ntex/src/connect/rustls.rs b/ntex/src/connect/rustls.rs index 5895beb6..32862b8d 100644 --- a/ntex/src/connect/rustls.rs +++ b/ntex/src/connect/rustls.rs @@ -10,7 +10,7 @@ use crate::rt::net::TcpStream; use crate::service::{Service, ServiceFactory}; use crate::util::Ready; -use super::{Address, Connect, ConnectError, Connector, DnsResolver}; +use super::{Address, Connect, ConnectError, Connector}; /// Rustls connector factory pub struct RustlsConnector { @@ -25,14 +25,6 @@ impl RustlsConnector { connector: Connector::default(), } } - - /// Construct new connect service with custom dns resolver - pub fn with_resolver(config: Arc, resolver: DnsResolver) -> Self { - RustlsConnector { - config, - connector: Connector::new(resolver), - } - } } impl RustlsConnector { diff --git a/ntex/src/connect/service.rs b/ntex/src/connect/service.rs index 1e76e455..f4177f94 100644 --- a/ntex/src/connect/service.rs +++ b/ntex/src/connect/service.rs @@ -5,7 +5,7 @@ use crate::rt::net::TcpStream; use crate::service::{Service, ServiceFactory}; use crate::util::{Either, Ready}; -use super::{Address, Connect, ConnectError, DnsResolver, Resolver}; +use super::{Address, Connect, ConnectError, Resolver}; pub struct Connector { resolver: Resolver, @@ -13,9 +13,9 @@ pub struct Connector { impl Connector { /// Construct new connect service with custom dns resolver - pub fn new(resolver: DnsResolver) -> Self { + pub fn new() -> Self { Connector { - resolver: Resolver::new(resolver), + resolver: Resolver::new(), } } } diff --git a/ntex/src/http/client/connector.rs b/ntex/src/http/client/connector.rs index be7f2d20..2db1fc79 100644 --- a/ntex/src/http/client/connector.rs +++ b/ntex/src/http/client/connector.rs @@ -1,7 +1,7 @@ use std::{rc::Rc, task::Context, task::Poll, time::Duration}; use crate::codec::{AsyncRead, AsyncWrite}; -use crate::connect::{self, Connect as TcpConnect, Connector as TcpConnector}; +use crate::connect::{Connect as TcpConnect, Connector as TcpConnector}; use crate::http::{Protocol, Uri}; use crate::service::{apply_fn, boxed, Service}; use crate::util::timeout::{TimeoutError, TimeoutService}; @@ -44,8 +44,6 @@ pub struct Connector { limit: usize, connector: BoxedConnector, ssl_connector: Option, - #[allow(dead_code)] - resolver: connect::DnsResolver, } trait Io: AsyncRead + AsyncWrite + Unpin {} @@ -53,15 +51,15 @@ impl Io for T {} impl Default for Connector { fn default() -> Self { - Connector::new(connect::default_resolver()) + Connector::new() } } impl Connector { - pub fn new(resolver: connect::DnsResolver) -> Connector { + pub fn new() -> Connector { let conn = Connector { connector: boxed::service( - TcpConnector::new(resolver.clone()) + TcpConnector::new() .map(|io| (Box::new(io) as Box, Protocol::Http1)) .map_err(ConnectError::from), ), @@ -71,7 +69,6 @@ impl Connector { conn_keep_alive: Duration::from_secs(15), disconnect_timeout: Duration::from_millis(3000), limit: 100, - resolver, }; #[cfg(feature = "openssl")] @@ -114,23 +111,19 @@ impl Connector { pub fn openssl(self, connector: OpensslConnector) -> Self { use crate::connect::openssl::OpensslConnector; - let resolver = self.resolver.clone(); - const H2: &[u8] = b"h2"; - self.secure_connector(OpensslConnector::with_resolver(connector, resolver).map( - |sock| { - let h2 = sock - .ssl() - .selected_alpn_protocol() - .map(|protos| protos.windows(2).any(|w| w == H2)) - .unwrap_or(false); - if h2 { - (sock, Protocol::Http2) - } else { - (sock, Protocol::Http1) - } - }, - )) + self.secure_connector(OpensslConnector::new(connector).map(|sock| { + let h2 = sock + .ssl() + .selected_alpn_protocol() + .map(|protos| protos.windows(2).any(|w| w == H2)) + .unwrap_or(false); + if h2 { + (sock, Protocol::Http2) + } else { + (sock, Protocol::Http1) + } + })) } #[cfg(feature = "rustls")] @@ -138,24 +131,20 @@ impl Connector { pub fn rustls(self, connector: Arc) -> Self { use crate::connect::rustls::{RustlsConnector, Session}; - let resolver = self.resolver.clone(); - const H2: &[u8] = b"h2"; - self.secure_connector(RustlsConnector::with_resolver(connector, resolver).map( - |sock| { - let h2 = sock - .get_ref() - .1 - .get_alpn_protocol() - .map(|protos| protos.windows(2).any(|w| w == H2)) - .unwrap_or(false); - if h2 { - (Box::new(sock) as Box, Protocol::Http2) - } else { - (Box::new(sock) as Box, Protocol::Http1) - } - }, - )) + self.secure_connector(RustlsConnector::new(connector).map(|sock| { + let h2 = sock + .get_ref() + .1 + .get_alpn_protocol() + .map(|protos| protos.windows(2).any(|w| w == H2)) + .unwrap_or(false); + if h2 { + (Box::new(sock) as Box, Protocol::Http2) + } else { + (Box::new(sock) as Box, Protocol::Http1) + } + })) } /// Set total number of simultaneous connections per type of scheme. diff --git a/ntex/src/http/client/error.rs b/ntex/src/http/client/error.rs index fa43d141..c6ba2f23 100644 --- a/ntex/src/http/client/error.rs +++ b/ntex/src/http/client/error.rs @@ -6,7 +6,6 @@ use serde_json::error::Error as JsonError; #[cfg(feature = "openssl")] use crate::connect::openssl::{HandshakeError, SslError}; -use crate::connect::ResolveError; use crate::http::error::{HttpError, ParseError, PayloadError}; use crate::http::header::HeaderValue; @@ -91,8 +90,9 @@ pub enum ConnectError { SslHandshakeError(String), /// Failed to resolve the hostname + #[from(ignore)] #[display(fmt = "Failed resolving hostname: {}", _0)] - Resolver(ResolveError), + Resolver(io::Error), /// No dns records #[display(fmt = "No dns records found for the input")] diff --git a/ntex/tests/connect.rs b/ntex/tests/connect.rs index 55fdceb3..c35bef2b 100644 --- a/ntex/tests/connect.rs +++ b/ntex/tests/connect.rs @@ -4,7 +4,7 @@ use bytes::Bytes; use futures::SinkExt; use ntex::codec::{BytesCodec, Framed}; -use ntex::connect::{Connect, ResolverConfig, ResolverOpts}; +use ntex::connect::Connect; use ntex::rt::net::TcpStream; use ntex::server::test_server; use ntex::service::{fn_service, Service, ServiceFactory}; @@ -53,14 +53,13 @@ async fn test_static_str() { }) }); - let resolver = ntex::connect::default_resolver(); - let conn = ntex::connect::Connector::new(resolver.clone()); + let conn = ntex::connect::Connector::new(); let con = conn.call(Connect::with("10", srv.addr())).await.unwrap(); assert_eq!(con.peer_addr().unwrap(), srv.addr()); let connect = Connect::new("127.0.0.1".to_owned()); - let conn = ntex::connect::Connector::new(resolver); + let conn = ntex::connect::Connector::new(); let con = conn.call(connect).await; assert!(con.is_err()); } @@ -75,13 +74,7 @@ async fn test_new_service() { }) }); - let resolver = ntex::connect::start_resolver( - ResolverConfig::default(), - ResolverOpts::default(), - ); - - let factory = ntex::connect::Connector::new(resolver); - + let factory = ntex::connect::Connector::new(); let conn = factory.new_service(()).await.unwrap(); let con = conn.call(Connect::with("10", srv.addr())).await.unwrap(); assert_eq!(con.peer_addr().unwrap(), srv.addr()); diff --git a/ntex/tests/http_awc_client.rs b/ntex/tests/http_awc_client.rs index efa9cf0e..49d1cab9 100644 --- a/ntex/tests/http_awc_client.rs +++ b/ntex/tests/http_awc_client.rs @@ -176,7 +176,7 @@ async fn test_timeout() { let connector = Connector::default() .connector( - ntex::connect::Connector::new(ntex::connect::default_resolver()) + ntex::connect::Connector::new() .map(|sock| (sock, ntex::http::Protocol::Http1)), ) .timeout(Duration::from_secs(15)) diff --git a/ntex/tests/http_server.rs b/ntex/tests/http_server.rs index 8b900d95..77d2a4d1 100644 --- a/ntex/tests/http_server.rs +++ b/ntex/tests/http_server.rs @@ -143,7 +143,7 @@ async fn test_chunked_payload() { let mut data = String::new(); let _ = stream.read_to_string(&mut data); - let re = Regex::new(r"size=(\d+)").unwrap(); + let re = Regex::new(r"size=([0-9]+)").unwrap(); let size: usize = match re.captures(&data) { Some(caps) => caps.get(1).unwrap().as_str().parse().unwrap(), None => panic!("Failed to find size in HTTP Response: {}", data),