Stop using the url crate in the proxy. (#450)

Version 1.7.0 of the url crate seems to be broken which means we cannot
`cargo update` the proxy without locking url to version 1.6. Since we only
use it in a very limited way anyway, and since we use http::uri for parsing
much more, just switch all uses of the url crate to use http::uri for parsing
instead.

This eliminates some build dependencies.

Signed-off-by: Brian Smith <brian@briansmith.org>
This commit is contained in:
Brian Smith 2018-02-26 08:55:48 -10:00 committed by GitHub
parent 694f691b71
commit 8607875267
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 89 additions and 97 deletions

44
Cargo.lock generated
View File

@ -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)" = "<none>"
"checksum tower-util 0.1.0 (git+https://github.com/tower-rs/tower)" = "<none>"
"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"

View File

@ -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"

View File

@ -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<Self, Self::Err> {
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<T>(s: &str) -> Result<T, ParseError> where T: FromStr {
}
fn parse_url(s: &str) -> Result<HostAndPort, ParseError> {
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::<http::Uri>().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<T, Parse>(strings: &Strings, name: &str, parse: Parse) -> Result<Option<T>, Error>

View File

@ -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),

View File

@ -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),
}
}
}

View File

@ -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::*;

View File

@ -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<C> = timeout::Timeout<C>;
// ===== impl HostAndPort =====
impl<'a> convert::TryFrom<&'a http::uri::Authority> for HostAndPort {
type Err = HostAndPortError;
fn try_from(a: &http::uri::Authority) -> Result<Self, Self::Err> {
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)

View File

@ -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};

View File

@ -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};