diff --git a/Cargo.lock b/Cargo.lock index 9031946fb..4f28c9f5a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -150,7 +150,6 @@ dependencies = [ "tower-in-flight-limit 0.1.0 (git+https://github.com/tower-rs/tower)", "tower-reconnect 0.1.0 (git+https://github.com/tower-rs/tower)", "tower-util 0.1.0 (git+https://github.com/tower-rs/tower)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -383,16 +382,6 @@ dependencies = [ "unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "idna" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "iovec" version = "0.1.2" @@ -471,11 +460,6 @@ dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "matches" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "memchr" version = "2.0.1" @@ -1080,19 +1064,6 @@ dependencies = [ "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "unicode-bidi" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-normalization" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "unicode-segmentation" version = "1.2.0" @@ -1116,16 +1087,6 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "url" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "utf8-ranges" version = "1.0.0" @@ -1232,7 +1193,6 @@ dependencies = [ "checksum http 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf8217d8829cc05dedadc08b4bc0684e5e3fbba1126c5edc680af49053fa230c" "checksum httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f407128745b78abc95c0ffbe4e5d37427fdc0d45470710cfef8c44522a2e37" "checksum hyper 0.11.19 (registry+https://github.com/rust-lang/crates.io-index)" = "47659bb1cb7ef3cd7b4f9bd2a11349b8d92097d34f9597a3c09e9bcefaf92b61" -"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum ipnet 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51268c3a27ad46afd1cca0bbf423a5be2e9fd3e6a7534736c195f0f834b763ef" "checksum itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b07332223953b5051bceb67e8c4700aa65291535568e1f12408c43c4a42c0394" @@ -1244,7 +1204,6 @@ dependencies = [ "checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" -"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e00e17be181010a91dbfefb01660b17311059dc8c7f48b9017677721e732bd" "checksum miniz_oxide 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aaa2d3ad070f428fffbd7d3ca2ea20bb0d8cffe9024405c44e1840bc1418b398" @@ -1313,13 +1272,10 @@ dependencies = [ "checksum tower-reconnect 0.1.0 (git+https://github.com/tower-rs/tower)" = "" "checksum tower-util 0.1.0 (git+https://github.com/tower-rs/tower)" = "" "checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a" -"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa35e768d4daf1d85733418a49fb42e10d7f633e394fccab4ab7aba897053fe2" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b" "checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" diff --git a/proxy/Cargo.toml b/proxy/Cargo.toml index ca005f7e6..def48f3ad 100644 --- a/proxy/Cargo.toml +++ b/proxy/Cargo.toml @@ -27,7 +27,6 @@ ipnet = "1.0" log = "0.3" ordermap = "0.2" rand = "0.4" -url = "1.5" tokio-core = "0.1" tokio-io = "0.1" diff --git a/proxy/src/config.rs b/proxy/src/config.rs index b1763b36d..304bcabd8 100644 --- a/proxy/src/config.rs +++ b/proxy/src/config.rs @@ -5,8 +5,9 @@ use std::path::PathBuf; use std::str::FromStr; use std::time::Duration; -use url::{Host, HostAndPort, Url}; +use http; +use transport::{Host, HostAndPort, HostAndPortError}; use convert::TryFrom; // TODO: @@ -104,17 +105,14 @@ pub enum UrlError { /// The URL has a scheme that isn't supported. UnsupportedScheme, - /// The URL is missing the host part. - MissingHost, + /// The URL is missing the authority part. + MissingAuthority, - /// The URL is missing the port and there is no default port. - MissingPort, + /// The URL is missing the authority part. + AuthorityError(HostAndPortError), /// The URL contains a path component that isn't "/", which isn't allowed. PathNotAllowed, - - /// The URL contains a fragment, which isn't allowed. - FragmentNotAllowed, } /// The strings used to build a configuration. @@ -265,20 +263,11 @@ impl FromStr for Addr { type Err = ParseError; fn from_str(s: &str) -> Result { - match parse_url(s)? { - HostAndPort { - host: Host::Ipv4(ip), - port, - } => Ok(Addr(SocketAddr::new(ip.into(), port))), - HostAndPort { - host: Host::Ipv6(ip), - port, - } => Ok(Addr(SocketAddr::new(ip.into(), port))), - HostAndPort { - host: Host::Domain(_), - .. - } => Err(ParseError::HostIsNotAnIpAddress), + let a = parse_url(s)?; + if let Host::Ip(ip) = a.host { + return Ok(Addr(SocketAddr::from((ip, a.port)))); } + Err(ParseError::HostIsNotAnIpAddress) } } @@ -337,24 +326,22 @@ fn parse_number(s: &str) -> Result where T: FromStr { } fn parse_url(s: &str) -> Result { - let url = Url::parse(&s).map_err(|_| ParseError::UrlError(UrlError::SyntaxError))?; - let host = url.host() - .ok_or_else(|| ParseError::UrlError(UrlError::MissingHost))? - .to_owned(); - if url.scheme() != "tcp" { + let url = s.parse::().map_err(|_| ParseError::UrlError(UrlError::SyntaxError))?; + if url.scheme_part().map(|s| s.as_str()) != Some("tcp") { return Err(ParseError::UrlError(UrlError::UnsupportedScheme)); } - let port = url.port().ok_or_else(|| ParseError::UrlError(UrlError::MissingPort))?; + let authority = url.authority_part() + .ok_or_else(|| ParseError::UrlError(UrlError::MissingAuthority))?; + if url.path() != "/" { return Err(ParseError::UrlError(UrlError::PathNotAllowed)); } - if url.fragment().is_some() { - return Err(ParseError::UrlError(UrlError::FragmentNotAllowed)); - } - Ok(HostAndPort { - host, - port, - }) + // http::Uri doesn't provde an accessor for the fragment; See + // https://github.com/hyperium/http/issues/127. For now just ignore any + // fragment that is there. + + HostAndPort::try_from(authority) + .map_err(|e| ParseError::UrlError(UrlError::AuthorityError(e))) } fn parse(strings: &Strings, name: &str, parse: Parse) -> Result, Error> diff --git a/proxy/src/control/mod.rs b/proxy/src/control/mod.rs index a0673560e..4014429e7 100644 --- a/proxy/src/control/mod.rs +++ b/proxy/src/control/mod.rs @@ -15,11 +15,10 @@ use tokio_core::reactor::{ use tower::Service; use tower_h2; use tower_reconnect::{Error as ReconnectError, Reconnect}; -use url::HostAndPort; use dns; use fully_qualified_authority::FullyQualifiedAuthority; -use transport::LookupAddressAndConnect; +use transport::{HostAndPort, LookupAddressAndConnect}; use timeout::{Timeout, TimeoutError}; pub mod discovery; @@ -79,11 +78,9 @@ impl Background { { // Build up the Controller Client Stack let mut client = { - let ctx = ("controller-client", format!("{}", host_and_port)); + let ctx = ("controller-client", format!("{:?}", host_and_port)); let scheme = http::uri::Scheme::from_shared(Bytes::from_static(b"http")).unwrap(); - let authority = - http::uri::Authority::from_shared(format!("{}", host_and_port).into()).unwrap(); - + let authority = http::uri::Authority::from(&host_and_port); let dns_resolver = dns::Resolver::new(dns_config, executor); let connect = Timeout::new( LookupAddressAndConnect::new(host_and_port, dns_resolver, executor), diff --git a/proxy/src/dns.rs b/proxy/src/dns.rs index aea13d62a..39e0b239e 100644 --- a/proxy/src/dns.rs +++ b/proxy/src/dns.rs @@ -7,7 +7,7 @@ use std::net::IpAddr; use std::path::Path; use std::str::FromStr; use tokio_core::reactor::Handle; -use url; +use transport; #[derive(Clone, Debug)] pub struct Config(domain::resolv::ResolvConf); @@ -45,17 +45,16 @@ impl Resolver { )) } - pub fn resolve_host(&self, host: &url::Host) -> IpAddrFuture { + pub fn resolve_host(&self, host: &transport::Host) -> IpAddrFuture { match *host { - url::Host::Domain(ref name) => { + transport::Host::DnsName(ref name) => { trace!("resolve {}", name); match abstract_ns::Name::from_str(name) { Ok(name) => IpAddrFuture::DNS(self.0.resolve_host(&name)), Err(_) => IpAddrFuture::InvalidDNSName(name.clone()), } } - url::Host::Ipv4(ref addr) => IpAddrFuture::Fixed(IpAddr::V4(*addr)), - url::Host::Ipv6(ref addr) => IpAddrFuture::Fixed(IpAddr::V6(*addr)), + transport::Host::Ip(addr) => IpAddrFuture::Fixed(addr), } } } diff --git a/proxy/src/lib.rs b/proxy/src/lib.rs index 456d2dacd..2b194ab31 100644 --- a/proxy/src/lib.rs +++ b/proxy/src/lib.rs @@ -41,7 +41,6 @@ extern crate tower_reconnect; extern crate conduit_proxy_router; extern crate tower_util; extern crate tower_in_flight_limit; -extern crate url; use futures::*; diff --git a/proxy/src/transport/connect.rs b/proxy/src/transport/connect.rs index c77712db5..a233bf3ab 100644 --- a/proxy/src/transport/connect.rs +++ b/proxy/src/transport/connect.rs @@ -1,12 +1,15 @@ use futures::Future; use tokio_connect; use tokio_core::reactor::Handle; -use url; use std::io; use std::net::{IpAddr, SocketAddr}; +use std::str::FromStr; + +use http; use connection; +use convert; use dns; use ::timeout; @@ -16,15 +19,63 @@ pub struct Connect { handle: Handle, } +#[derive(Clone, Debug)] +pub struct HostAndPort { + pub host: Host, + pub port: u16, +} + +#[derive(Clone, Debug)] +pub enum Host { + DnsName(String), + Ip(IpAddr), +} + +#[derive(Clone, Copy, Debug)] +pub enum HostAndPortError { + /// The port is missing. + MissingPort, +} + #[derive(Debug, Clone)] pub struct LookupAddressAndConnect { - host_and_port: url::HostAndPort, + host_and_port: HostAndPort, dns_resolver: dns::Resolver, handle: Handle, } pub type TimeoutConnect = timeout::Timeout; +// ===== impl HostAndPort ===== + +impl<'a> convert::TryFrom<&'a http::uri::Authority> for HostAndPort { + type Err = HostAndPortError; + fn try_from(a: &http::uri::Authority) -> Result { + let host = { + let host = a.host(); + match IpAddr::from_str(host) { + Err(_) => Host::DnsName(host.to_owned()), + Ok(ip) => Host::Ip(ip), + } + }; + let port = a.port().ok_or_else(|| HostAndPortError::MissingPort)?; + Ok(HostAndPort { + host, + port + }) + } +} + +impl<'a> From<&'a HostAndPort> for http::uri::Authority { + fn from(a: &HostAndPort) -> Self { + let s = match a.host { + Host::DnsName(ref n) => format!("{}:{}", n, a.port), + Host::Ip(ref ip) => format!("{}:{}", ip, a.port), + }; + http::uri::Authority::from_str(&s).unwrap() + } +} + // ===== impl Connect ===== impl Connect { @@ -51,7 +102,7 @@ impl tokio_connect::Connect for Connect { impl LookupAddressAndConnect { pub fn new( - host_and_port: url::HostAndPort, + host_and_port: HostAndPort, dns_resolver: dns::Resolver, handle: &Handle, ) -> Self { @@ -78,7 +129,7 @@ impl tokio_connect::Connect for LookupAddressAndConnect { io::Error::new(io::ErrorKind::NotFound, "DNS resolution failed") }) .and_then(move |ip_addr: IpAddr| { - info!("DNS resolved {} to {}", host, ip_addr); + info!("DNS resolved {:?} to {}", host, ip_addr); let addr = SocketAddr::from((ip_addr, port)); trace!("connect {}", addr); connection::connect(&addr, &handle) diff --git a/proxy/src/transport/mod.rs b/proxy/src/transport/mod.rs index 076a3bfce..6adf87e83 100644 --- a/proxy/src/transport/mod.rs +++ b/proxy/src/transport/mod.rs @@ -1,5 +1,10 @@ mod connect; mod so_original_dst; -pub use self::connect::{Connect, LookupAddressAndConnect, TimeoutConnect}; +pub use self::connect::{ + Connect, + Host, HostAndPort, HostAndPortError, + LookupAddressAndConnect, + TimeoutConnect +}; pub use self::so_original_dst::{GetOriginalDst, SoOriginalDst}; diff --git a/proxy/tests/support/mod.rs b/proxy/tests/support/mod.rs index 23c9443ab..a6b69bdb6 100644 --- a/proxy/tests/support/mod.rs +++ b/proxy/tests/support/mod.rs @@ -14,7 +14,6 @@ extern crate tokio_core; pub extern crate tokio_io; extern crate tower; extern crate tower_h2; -extern crate url; pub extern crate env_logger; use self::bytes::{BigEndian, Bytes, BytesMut};