diff options
author | Justus Winter <teythoon@avior.uberspace.de> | 2018-03-04 16:51:49 +0100 |
---|---|---|
committer | Justus Winter <teythoon@avior.uberspace.de> | 2018-03-04 16:51:49 +0100 |
commit | c993ced88008ba7046938e46658a10e0dd624c99 (patch) | |
tree | 3c47916c3d4ac4b408a9d3c9bae9b83eb4ad6245 /net | |
parent | 2fc6905004e0bebf23658ff2a57a4ac6f04f194c (diff) |
net: Use the url crate for URL manipulation.
- The url crate is more expressive than hyper::Uri and among other
things features a 'join' operation.
- This fixes malformed URLs being created by the net module where we
naively using string operations instead of the proper join
operation.
Diffstat (limited to 'net')
-rw-r--r-- | net/src/async.rs | 45 | ||||
-rw-r--r-- | net/src/lib.rs | 21 |
2 files changed, 38 insertions, 28 deletions
diff --git a/net/src/async.rs b/net/src/async.rs index e467e83a..27b5b44b 100644 --- a/net/src/async.rs +++ b/net/src/async.rs @@ -7,13 +7,14 @@ use failure; use futures::{future, Future, Stream}; use hyper::client::{FutureResponse, HttpConnector}; use hyper::header::{ContentLength, ContentType}; -use hyper::{Client, Uri, StatusCode, Request, Method}; +use hyper::{self, Client, StatusCode, Request, Method}; use hyper_tls::HttpsConnector; use native_tls::{Certificate, TlsConnector}; use percent_encoding::{percent_encode, DEFAULT_ENCODE_SET}; use std::convert::From; use std::io::Cursor; use tokio_core::reactor::Handle; +use url::Url; use openpgp::tpk::TPK; use openpgp::{KeyID, armor}; @@ -32,7 +33,7 @@ define_encode_set! { /// For accessing keyservers using HKP. pub struct KeyServer { client: Box<AClient>, - uri: Uri, + uri: Url, } const DNS_WORKER: usize = 4; @@ -40,11 +41,11 @@ const DNS_WORKER: usize = 4; impl KeyServer { /// Returns a handle for the given URI. pub fn new(ctx: &Context, uri: &str, handle: &Handle) -> Result<Self> { - let uri: Uri = uri.parse()?; + let uri: Url = uri.parse()?; let client: Box<AClient> = match uri.scheme() { - Some("hkp") => Box::new(Client::new(handle)), - Some("hkps") => { + "hkp" => Box::new(Client::new(handle)), + "hkps" => { Box::new(Client::configure() .connector(HttpsConnector::new(DNS_WORKER, handle)?) .build(handle)) @@ -60,7 +61,7 @@ impl KeyServer { /// `cert` is used to authenticate the server. pub fn with_cert(ctx: &Context, uri: &str, cert: Certificate, handle: &Handle) -> Result<Self> { - let uri: Uri = uri.parse()?; + let uri: Url = uri.parse()?; let client: Box<AClient> = { let mut ssl = TlsConnector::builder()?; @@ -90,16 +91,17 @@ impl KeyServer { } /// Common code for the above functions. - fn make(ctx: &Context, client: Box<AClient>, uri: Uri) -> Result<Self> { - let s = uri.scheme().ok_or(Error::MalformedUri)?; + fn make(ctx: &Context, client: Box<AClient>, uri: Url) -> Result<Self> { + let s = uri.scheme(); match s { "hkp" => ctx.network_policy().assert(NetworkPolicy::Insecure), "hkps" => ctx.network_policy().assert(NetworkPolicy::Encrypted), - _ => unreachable!() + _ => return Err(Error::MalformedUri.into()) }?; let uri = format!("{}://{}:{}", - match s {"hkp" => "http", "hkps" => "https", _ => unreachable!()}, + match s {"hkp" => "http", "hkps" => "https", + _ => unreachable!()}, uri.host().ok_or(Error::MalformedUri)?, match s { "hkp" => uri.port().or(Some(11371)), @@ -113,8 +115,9 @@ impl KeyServer { /// Retrieves the key with the given `keyid`. pub fn get(&mut self, keyid: &KeyID) -> Box<Future<Item=TPK, Error=failure::Error> + 'static> { - let uri = format!("{}/pks/lookup?op=get&options=mr&search=0x{}", - self.uri, keyid.to_hex()).parse(); + let uri = self.uri.join( + &format!("pks/lookup?op=get&options=mr&search=0x{}", + keyid.to_hex())); if let Err(e) = uri { // This shouldn't happen, but better safe than sorry. return Box::new(future::err(Error::from(e).into())); @@ -143,7 +146,7 @@ impl KeyServer { use openpgp::armor::{Writer, Kind}; let uri = - match format!("{}/pks/add", self.uri).parse() { + match self.uri.join("pks/add") { Err(e) => // This shouldn't happen, but better safe than sorry. return Box::new(future::err(Error::from(e).into())), @@ -163,7 +166,7 @@ impl KeyServer { post_data.extend_from_slice(percent_encode(&armored_blob, KEYSERVER_ENCODE_SET) .collect::<String>().as_bytes()); - let mut request = Request::new(Method::Post, uri); + let mut request = Request::new(Method::Post, url2uri(uri)); request.headers_mut().set(ContentType::form_url_encoded()); request.headers_mut().set(ContentLength(post_data.len() as u64)); request.set_body(post_data); @@ -181,13 +184,13 @@ impl KeyServer { } trait AClient { - fn do_get(&mut self, uri: Uri) -> FutureResponse; + fn do_get(&mut self, uri: Url) -> FutureResponse; fn do_request(&mut self, request: Request) -> FutureResponse; } impl AClient for Client<HttpConnector> { - fn do_get(&mut self, uri: Uri) -> FutureResponse { - self.get(uri) + fn do_get(&mut self, uri: Url) -> FutureResponse { + self.get(url2uri(uri)) } fn do_request(&mut self, request: Request) -> FutureResponse { self.request(request) @@ -195,10 +198,14 @@ impl AClient for Client<HttpConnector> { } impl AClient for Client<HttpsConnector<HttpConnector>> { - fn do_get(&mut self, uri: Uri) -> FutureResponse { - self.get(uri) + fn do_get(&mut self, uri: Url) -> FutureResponse { + self.get(url2uri(uri)) } fn do_request(&mut self, request: Request) -> FutureResponse { self.request(request) } } + +pub(crate) fn url2uri(uri: Url) -> hyper::Uri { + format!("{}", uri).parse().unwrap() +} diff --git a/net/src/lib.rs b/net/src/lib.rs index 9161df53..94baaa05 100644 --- a/net/src/lib.rs +++ b/net/src/lib.rs @@ -43,21 +43,24 @@ extern crate tokio_core; extern crate tokio_io; #[macro_use] extern crate percent_encoding; +extern crate url; extern crate capnp_rpc; use hyper::client::{FutureResponse, HttpConnector}; -use hyper::{Client, Uri, Request}; +use hyper::{Client, Request}; use hyper_tls::HttpsConnector; use native_tls::Certificate; use std::convert::From; use tokio_core::reactor::Core; +use url::Url; use openpgp::KeyID; use openpgp::tpk::TPK; use sequoia_core::Context; pub mod async; +use async::url2uri; pub mod ipc; /// For accessing keyservers using HKP. @@ -111,13 +114,13 @@ impl KeyServer { } trait AClient { - fn do_get(&mut self, uri: Uri) -> FutureResponse; + fn do_get(&mut self, uri: Url) -> FutureResponse; fn do_request(&mut self, request: Request) -> FutureResponse; } impl AClient for Client<HttpConnector> { - fn do_get(&mut self, uri: Uri) -> FutureResponse { - self.get(uri) + fn do_get(&mut self, uri: Url) -> FutureResponse { + self.get(url2uri(uri)) } fn do_request(&mut self, request: Request) -> FutureResponse { self.request(request) @@ -125,8 +128,8 @@ impl AClient for Client<HttpConnector> { } impl AClient for Client<HttpsConnector<HttpConnector>> { - fn do_get(&mut self, uri: Uri) -> FutureResponse { - self.get(uri) + fn do_get(&mut self, uri: Url) -> FutureResponse { + self.get(url2uri(uri)) } fn do_request(&mut self, request: Request) -> FutureResponse { self.request(request) @@ -156,7 +159,7 @@ pub enum Error { HttpStatus(hyper::StatusCode), /// A `hyper::error::UriError` occurred. #[fail(display = "URI Error")] - UriError(hyper::error::UriError), + UriError(url::ParseError), /// A `hyper::Error` occurred. #[fail(display = "Hyper Error")] HyperError(hyper::Error), @@ -171,8 +174,8 @@ impl From<hyper::Error> for Error { } } -impl From<hyper::error::UriError> for Error { - fn from(e: hyper::error::UriError) -> Error { +impl From<url::ParseError> for Error { + fn from(e: url::ParseError) -> Error { Error::UriError(e) } } |