diff --git a/.rustfmt.toml b/.rustfmt.toml deleted file mode 100644 index c7ad93b..0000000 --- a/.rustfmt.toml +++ /dev/null @@ -1 +0,0 @@ -disable_all_formatting = true diff --git a/.travis.yml b/.travis.yml index c2a80c8..86dfb51 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,7 +55,9 @@ dist: trusty env: global: - REQWEST_TEST_BODY_FULL=1 - +before_script: + - rustup component add rustfmt script: + - cargo fmt -- --check - cargo build $FEATURES - cargo test -v $FEATURES -- --test-threads=1 diff --git a/examples/async.rs b/examples/async.rs index b372246..fbdb771 100644 --- a/examples/async.rs +++ b/examples/async.rs @@ -1,16 +1,11 @@ #![deny(warnings)] -extern crate futures; -extern crate reqwest; -extern crate tokio; - -use std::mem; -use std::io::{self, Cursor}; use futures::{Future, Stream}; use reqwest::r#async::{Client, Decoder}; +use std::io::{self, Cursor}; +use std::mem; - -fn fetch() -> impl Future { +fn fetch() -> impl Future { Client::new() .get("https://hyper.rs") .send() @@ -23,10 +18,9 @@ fn fetch() -> impl Future { .map_err(|err| println!("request error: {}", err)) .map(|body| { let mut body = Cursor::new(body); - let _ = io::copy(&mut body, &mut io::stdout()) - .map_err(|err| { - println!("stdout error: {}", err); - }); + let _ = io::copy(&mut body, &mut io::stdout()).map_err(|err| { + println!("stdout error: {}", err); + }); }) } diff --git a/examples/async_multiple_requests.rs b/examples/async_multiple_requests.rs index f52f499..2884023 100644 --- a/examples/async_multiple_requests.rs +++ b/examples/async_multiple_requests.rs @@ -1,11 +1,5 @@ #![deny(warnings)] -extern crate futures; -extern crate reqwest; -extern crate tokio; -extern crate serde; -extern crate serde_json; - use futures::Future; use reqwest::r#async::{Client, Response}; use serde::Deserialize; @@ -21,27 +15,18 @@ struct SlideshowContainer { slideshow: Slideshow, } -fn fetch() -> impl Future { +fn fetch() -> impl Future { let client = Client::new(); - let json = |mut res : Response | { - res.json::() - }; + let json = |mut res: Response| res.json::(); - let request1 = - client - .get("https://httpbin.org/json") - .send() - .and_then(json); + let request1 = client.get("https://httpbin.org/json").send().and_then(json); - let request2 = - client - .get("https://httpbin.org/json") - .send() - .and_then(json); + let request2 = client.get("https://httpbin.org/json").send().and_then(json); - request1.join(request2) - .map(|(res1, res2)|{ + request1 + .join(request2) + .map(|(res1, res2)| { println!("{:?}", res1); println!("{:?}", res2); }) diff --git a/examples/async_stream.rs b/examples/async_stream.rs index dbaf30a..6ebb7b3 100644 --- a/examples/async_stream.rs +++ b/examples/async_stream.rs @@ -1,18 +1,11 @@ #![deny(warnings)] -#[macro_use] -extern crate futures; -extern crate bytes; -extern crate reqwest; -extern crate tokio; -extern crate tokio_threadpool; - use std::io::{self, Cursor}; use std::mem; use std::path::Path; use bytes::Bytes; -use futures::{Async, Future, Poll, Stream}; +use futures::{try_ready, Async, Future, Poll, Stream}; use reqwest::r#async::{Client, Decoder}; use tokio::fs::File; use tokio::io::AsyncRead; diff --git a/examples/form.rs b/examples/form.rs index 41d1b82..7c8d059 100644 --- a/examples/form.rs +++ b/examples/form.rs @@ -1,5 +1,3 @@ -extern crate reqwest; - fn main() { reqwest::Client::new() .post("http://www.baidu.com") diff --git a/examples/json_dynamic.rs b/examples/json_dynamic.rs index 48676b9..fd5d520 100644 --- a/examples/json_dynamic.rs +++ b/examples/json_dynamic.rs @@ -3,19 +3,16 @@ //! This is useful for some ad-hoc experiments and situations when you don't //! really care about the structure of the JSON and just need to display it or //! process it at runtime. -extern crate reqwest; -#[macro_use] extern crate serde_json; +use serde_json::json; fn main() -> Result<(), reqwest::Error> { let echo_json: serde_json::Value = reqwest::Client::new() .post("https://jsonplaceholder.typicode.com/posts") - .json( - &json!({ - "title": "Reqwest.rs", - "body": "https://docs.rs/reqwest", - "userId": 1 - }) - ) + .json(&json!({ + "title": "Reqwest.rs", + "body": "https://docs.rs/reqwest", + "userId": 1 + })) .send()? .json()?; diff --git a/examples/json_typed.rs b/examples/json_typed.rs index 23770a9..1cbd218 100644 --- a/examples/json_typed.rs +++ b/examples/json_typed.rs @@ -3,9 +3,6 @@ //! In contrast to the arbitrary JSON example, this brings up the full power of //! Rust compile-time type system guaranties though it requires a little bit //! more code. -extern crate reqwest; -extern crate serde; -extern crate serde_json; use serde::{Deserialize, Serialize}; @@ -23,7 +20,7 @@ fn main() -> Result<(), reqwest::Error> { id: None, title: "Reqwest.rs".into(), body: "https://docs.rs/reqwest".into(), - user_id: 1 + user_id: 1, }; let new_post: Post = reqwest::Client::new() .post("https://jsonplaceholder.typicode.com/posts") diff --git a/examples/simple.rs b/examples/simple.rs index b8ec8ce..23cd99d 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -2,9 +2,6 @@ //! `cargo run --example simple` -extern crate reqwest; -extern crate env_logger; - fn main() -> Result<(), Box> { env_logger::init(); diff --git a/src/async_impl.rs b/src/async_impl.rs index f79eb61..5997f06 100644 --- a/src/async_impl.rs +++ b/src/async_impl.rs @@ -1,6 +1,6 @@ pub use self::body::{Body, Chunk}; -pub use self::decoder::{Decoder, ReadableChunks}; pub use self::client::{Client, ClientBuilder}; +pub use self::decoder::{Decoder, ReadableChunks}; pub use self::request::{Request, RequestBuilder}; pub use self::response::{Response, ResponseBuilderExt}; diff --git a/src/async_impl/body.rs b/src/async_impl/body.rs index e73ac4e..bf5e7e0 100644 --- a/src/async_impl/body.rs +++ b/src/async_impl/body.rs @@ -1,7 +1,7 @@ use std::fmt; -use futures::{Future, Stream, Poll, Async, try_ready}; use bytes::{Buf, Bytes}; +use futures::{try_ready, Async, Future, Poll, Stream}; use hyper::body::Payload; use tokio::timer::Delay; @@ -15,7 +15,7 @@ enum Inner { Hyper { body: hyper::Body, timeout: Option, - } + }, } impl Body { @@ -29,10 +29,7 @@ impl Body { #[inline] pub(crate) fn response(body: hyper::Body, timeout: Option) -> Body { Body { - inner: Inner::Hyper { - body, - timeout, - }, + inner: Inner::Hyper { body, timeout }, } } @@ -65,7 +62,7 @@ impl Body { Inner::Hyper { body, timeout } => { debug_assert!(timeout.is_none()); (None, body) - }, + } } } } @@ -77,14 +74,17 @@ impl Stream for Body { #[inline] fn poll(&mut self) -> Poll, Self::Error> { let opt = match self.inner { - Inner::Hyper { ref mut body, ref mut timeout } => { + Inner::Hyper { + ref mut body, + ref mut timeout, + } => { if let Some(ref mut timeout) = timeout { if let Async::Ready(()) = try_!(timeout.poll()) { return Err(crate::error::timedout(None)); } } try_ready!(body.poll_data().map_err(crate::error::from)) - }, + } Inner::Reusable(ref mut bytes) => { return if bytes.is_empty() { Ok(Async::Ready(None)) @@ -93,12 +93,10 @@ impl Stream for Body { *bytes = Bytes::new(); Ok(Async::Ready(Some(chunk))) }; - }, + } }; - Ok(Async::Ready(opt.map(|chunk| Chunk { - inner: chunk, - }))) + Ok(Async::Ready(opt.map(|chunk| Chunk { inner: chunk }))) } } @@ -161,7 +159,7 @@ impl Chunk { #[inline] pub(crate) fn from_chunk(chunk: Bytes) -> Chunk { Chunk { - inner: hyper::Chunk::from(chunk) + inner: hyper::Chunk::from(chunk), } } } @@ -197,7 +195,9 @@ impl std::ops::Deref for Chunk { impl Extend for Chunk { fn extend(&mut self, iter: T) - where T: IntoIterator { + where + T: IntoIterator, + { self.inner.extend(iter) } } @@ -219,7 +219,9 @@ impl From> for Chunk { impl From<&'static [u8]> for Chunk { fn from(slice: &'static [u8]) -> Chunk { - Chunk { inner: slice.into() } + Chunk { + inner: slice.into(), + } } } @@ -231,13 +233,17 @@ impl From for Chunk { impl From<&'static str> for Chunk { fn from(slice: &'static str) -> Chunk { - Chunk { inner: slice.into() } + Chunk { + inner: slice.into(), + } } } impl From for Chunk { fn from(bytes: Bytes) -> Chunk { - Chunk { inner: bytes.into() } + Chunk { + inner: bytes.into(), + } } } @@ -249,8 +255,7 @@ impl From for hyper::Chunk { impl fmt::Debug for Body { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Body") - .finish() + f.debug_struct("Body").finish() } } diff --git a/src/async_impl/client.rs b/src/async_impl/client.rs index 1670824..1472da3 100644 --- a/src/async_impl/client.rs +++ b/src/async_impl/client.rs @@ -1,26 +1,14 @@ -use std::{fmt, str}; +use std::net::IpAddr; use std::sync::{Arc, RwLock}; use std::time::Duration; -use std::net::IpAddr; +use std::{fmt, str}; +use crate::header::{ + Entry, HeaderMap, HeaderValue, ACCEPT, ACCEPT_ENCODING, CONTENT_ENCODING, CONTENT_LENGTH, + CONTENT_TYPE, LOCATION, PROXY_AUTHORIZATION, RANGE, REFERER, TRANSFER_ENCODING, USER_AGENT, +}; use bytes::Bytes; use futures::{Async, Future, Poll}; -use crate::header::{ - Entry, - HeaderMap, - HeaderValue, - ACCEPT, - ACCEPT_ENCODING, - CONTENT_LENGTH, - CONTENT_ENCODING, - CONTENT_TYPE, - LOCATION, - PROXY_AUTHORIZATION, - RANGE, - REFERER, - TRANSFER_ENCODING, - USER_AGENT, -}; use http::Uri; use hyper::client::ResponseFuture; use mime; @@ -28,24 +16,22 @@ use mime; use native_tls::TlsConnector; use tokio::{clock, timer::Delay}; -use log::{debug}; - +use log::debug; use super::request::{Request, RequestBuilder}; use super::response::Response; use crate::connect::Connector; -use crate::into_url::{expect_uri, try_uri}; use crate::cookie; -use crate::redirect::{self, RedirectPolicy, remove_sensitive_headers}; -use crate::{IntoUrl, Method, Proxy, StatusCode, Url}; +use crate::into_url::{expect_uri, try_uri}; use crate::proxy::get_proxies; -#[cfg(feature = "tls")] -use crate::{Certificate, Identity}; +use crate::redirect::{self, remove_sensitive_headers, RedirectPolicy}; #[cfg(feature = "tls")] use crate::tls::TlsBackend; +#[cfg(feature = "tls")] +use crate::{Certificate, Identity}; +use crate::{IntoUrl, Method, Proxy, StatusCode, Url}; -static DEFAULT_USER_AGENT: &str = - concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")); +static DEFAULT_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")); /// An asynchronous `Client` to make Requests with. /// @@ -98,7 +84,10 @@ impl ClientBuilder { pub fn new() -> ClientBuilder { let mut headers: HeaderMap = HeaderMap::with_capacity(2); headers.insert(USER_AGENT, HeaderValue::from_static(DEFAULT_USER_AGENT)); - headers.insert(ACCEPT, HeaderValue::from_str(mime::STAR_STAR.as_ref()).expect("unable to parse mime")); + headers.insert( + ACCEPT, + HeaderValue::from_str(mime::STAR_STAR.as_ref()).expect("unable to parse mime"), + ); ClientBuilder { config: Config { @@ -156,8 +145,13 @@ impl ClientBuilder { id.add_to_native_tls(&mut tls)?; } - Connector::new_default_tls(tls, proxies.clone(), config.local_address, config.nodelay)? - }, + Connector::new_default_tls( + tls, + proxies.clone(), + config.local_address, + config.nodelay, + )? + } #[cfg(feature = "rustls-tls")] TlsBackend::Rustls => { use crate::tls::NoVerifier; @@ -166,15 +160,14 @@ impl ClientBuilder { if config.http2_only { tls.set_protocols(&["h2".into()]); } else { - tls.set_protocols(&[ - "h2".into(), - "http/1.1".into(), - ]); + tls.set_protocols(&["h2".into(), "http/1.1".into()]); } - tls.root_store.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); + tls.root_store + .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); if !config.certs_verification { - tls.dangerous().set_certificate_verifier(Arc::new(NoVerifier)); + tls.dangerous() + .set_certificate_verifier(Arc::new(NoVerifier)); } for cert in config.root_certs { @@ -185,7 +178,12 @@ impl ClientBuilder { id.add_to_rustls(&mut tls)?; } - Connector::new_rustls_tls(tls, proxies.clone(), config.local_address, config.nodelay)? + Connector::new_rustls_tls( + tls, + proxies.clone(), + config.local_address, + config.nodelay, + )? } } @@ -208,9 +206,7 @@ impl ClientBuilder { let hyper_client = builder.build(connector); - let proxies_maybe_http_auth = proxies - .iter() - .any(|p| p.maybe_has_http_auth()); + let proxies_maybe_http_auth = proxies.iter().any(|p| p.maybe_has_http_auth()); let cookie_store = config.cookie_store.map(RwLock::new); @@ -277,7 +273,10 @@ impl ClientBuilder { /// site will be trusted for use from any other. This introduces a /// significant vulnerability to man-in-the-middle attacks. #[cfg(feature = "default-tls")] - pub fn danger_accept_invalid_hostnames(mut self, accept_invalid_hostname: bool) -> ClientBuilder { + pub fn danger_accept_invalid_hostnames( + mut self, + accept_invalid_hostname: bool, + ) -> ClientBuilder { self.config.hostname_verification = !accept_invalid_hostname; self } @@ -299,7 +298,6 @@ impl ClientBuilder { self } - /// Sets the default headers for every request. pub fn default_headers(mut self, headers: HeaderMap) -> ClientBuilder { for (key, value) in headers.iter() { @@ -349,7 +347,6 @@ impl ClientBuilder { self } - /// Set a `RedirectPolicy` for this client. /// /// Default will follow redirects up to a maximum of 10. @@ -454,9 +451,7 @@ impl Client { /// Use `Client::builder()` if you wish to handle the failure as an `Error` /// instead of panicking. pub fn new() -> Client { - ClientBuilder::new() - .build() - .expect("Client::new()") + ClientBuilder::new().build().expect("Client::new()") } /// Creates a `ClientBuilder` to configure a `Client`. @@ -529,9 +524,7 @@ impl Client { /// /// This method fails whenever supplied `Url` cannot be parsed. pub fn request(&self, method: Method, url: U) -> RequestBuilder { - let req = url - .into_url() - .map(move |url| Request::new(method, url)); + let req = url.into_url().map(move |url| Request::new(method, url)); RequestBuilder::new(self.clone(), req) } @@ -551,14 +544,8 @@ impl Client { self.execute_request(request) } - pub(super) fn execute_request(&self, req: Request) -> Pending { - let ( - method, - url, - mut headers, - body - ) = req.pieces(); + let (method, url, mut headers, body) = req.pieces(); // insert default headers in the request headers // without overwriting already appended headers. @@ -576,9 +563,8 @@ impl Client { } } - if self.inner.gzip && - !headers.contains_key(ACCEPT_ENCODING) && - !headers.contains_key(RANGE) { + if self.inner.gzip && !headers.contains_key(ACCEPT_ENCODING) && !headers.contains_key(RANGE) + { headers.insert(ACCEPT_ENCODING, HeaderValue::from_static("gzip")); } @@ -588,10 +574,8 @@ impl Client { Some(body) => { let (reusable, body) = body.into_hyper(); (Some(reusable), body) - }, - None => { - (None, hyper::Body::empty()) } + None => (None, hyper::Body::empty()), }; self.proxy_auth(&uri, &mut headers); @@ -606,9 +590,10 @@ impl Client { let in_flight = self.inner.hyper.request(req); - let timeout = self.inner.request_timeout.map(|dur| { - Delay::new(clock::now() + dur) - }); + let timeout = self + .inner + .request_timeout + .map(|dur| Delay::new(clock::now() + dur)); Pending { inner: PendingInner::Request(PendingRequest { @@ -643,14 +628,10 @@ impl Client { return; } - for proxy in self.inner.proxies.iter() { if proxy.is_match(dst) { if let Some(header) = proxy.http_basic_auth(dst) { - headers.insert( - PROXY_AUTHORIZATION, - header, - ); + headers.insert(PROXY_AUTHORIZATION, header); } break; @@ -671,8 +652,7 @@ impl fmt::Debug for Client { impl fmt::Debug for ClientBuilder { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("ClientBuilder") - .finish() + f.debug_struct("ClientBuilder").finish() } } @@ -726,7 +706,9 @@ impl Future for Pending { fn poll(&mut self) -> Poll { match self.inner { PendingInner::Request(ref mut req) => req.poll(), - PendingInner::Error(ref mut err) => Err(err.take().expect("Pending error polled more than once")), + PendingInner::Error(ref mut err) => { + Err(err.take().expect("Pending error polled more than once")) + } } } } @@ -755,56 +737,58 @@ impl Future for PendingRequest { store.0.store_response_cookies(cookies, &self.url); } let should_redirect = match res.status() { - StatusCode::MOVED_PERMANENTLY | - StatusCode::FOUND | - StatusCode::SEE_OTHER => { + StatusCode::MOVED_PERMANENTLY | StatusCode::FOUND | StatusCode::SEE_OTHER => { self.body = None; - for header in &[TRANSFER_ENCODING, CONTENT_ENCODING, CONTENT_TYPE, CONTENT_LENGTH] { + for header in &[ + TRANSFER_ENCODING, + CONTENT_ENCODING, + CONTENT_TYPE, + CONTENT_LENGTH, + ] { self.headers.remove(header); } match self.method { - Method::GET | Method::HEAD => {}, + Method::GET | Method::HEAD => {} _ => { self.method = Method::GET; } } true - }, - StatusCode::TEMPORARY_REDIRECT | - StatusCode::PERMANENT_REDIRECT => match self.body { - Some(Some(_)) | None => true, - Some(None) => false, - }, + } + StatusCode::TEMPORARY_REDIRECT | StatusCode::PERMANENT_REDIRECT => { + match self.body { + Some(Some(_)) | None => true, + Some(None) => false, + } + } _ => false, }; if should_redirect { - let loc = res.headers() - .get(LOCATION) - .and_then(|val| { - let loc = (|| -> Option { - // Some sites may send a utf-8 Location header, - // even though we're supposed to treat those bytes - // as opaque, we'll check specifically for utf8. - self.url.join(str::from_utf8(val.as_bytes()).ok()?).ok() - })(); + let loc = res.headers().get(LOCATION).and_then(|val| { + let loc = (|| -> Option { + // Some sites may send a utf-8 Location header, + // even though we're supposed to treat those bytes + // as opaque, we'll check specifically for utf8. + self.url.join(str::from_utf8(val.as_bytes()).ok()?).ok() + })(); - // Check that the `url` is also a valid `http::Uri`. - // - // If not, just log it and skip the redirect. - let loc = loc.and_then(|url| { - if try_uri(&url).is_some() { - Some(url) - } else { - None - } - }); - - if loc.is_none() { - debug!("Location header had invalid URI: {:?}", val); + // Check that the `url` is also a valid `http::Uri`. + // + // If not, just log it and skip the redirect. + let loc = loc.and_then(|url| { + if try_uri(&url).is_some() { + Some(url) + } else { + None } - loc }); + + if loc.is_none() { + debug!("Location header had invalid URI: {:?}", val); + } + loc + }); if let Some(loc) = loc { if self.client.referer { if let Some(referer) = make_referer(&loc, &self.url) { @@ -812,11 +796,10 @@ impl Future for PendingRequest { } } self.urls.push(self.url.clone()); - let action = self.client.redirect_policy.check( - res.status(), - &loc, - &self.urls, - ); + let action = self + .client + .redirect_policy + .check(res.status(), &loc, &self.urls); match action { redirect::Action::Follow => { @@ -844,13 +827,13 @@ impl Future for PendingRequest { *req.headers_mut() = self.headers.clone(); self.in_flight = self.client.hyper.request(req); continue; - }, + } redirect::Action::Stop => { debug!("redirect_policy disallowed redirection to '{}'", loc); - }, + } redirect::Action::LoopDetected => { return Err(crate::error::loop_detected(self.url.clone())); - }, + } redirect::Action::TooManyRedirects => { return Err(crate::error::too_many_redirects(self.url.clone())); } @@ -866,17 +849,12 @@ impl Future for PendingRequest { impl fmt::Debug for Pending { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.inner { - PendingInner::Request(ref req) => { - f.debug_struct("Pending") - .field("method", &req.method) - .field("url", &req.url) - .finish() - }, - PendingInner::Error(ref err) => { - f.debug_struct("Pending") - .field("error", err) - .finish() - } + PendingInner::Request(ref req) => f + .debug_struct("Pending") + .field("method", &req.method) + .field("url", &req.url) + .finish(), + PendingInner::Error(ref err) => f.debug_struct("Pending").field("error", err).finish(), } } } @@ -903,7 +881,7 @@ fn add_cookie_header(headers: &mut HeaderMap, cookie_store: &cookie::CookieStore if !header.is_empty() { headers.insert( crate::header::COOKIE, - HeaderValue::from_bytes(header.as_bytes()).unwrap() + HeaderValue::from_bytes(header.as_bytes()).unwrap(), ); } } diff --git a/src/async_impl/decoder.rs b/src/async_impl/decoder.rs index d433a8c..3f95bd4 100644 --- a/src/async_impl/decoder.rs +++ b/src/async_impl/decoder.rs @@ -20,18 +20,18 @@ The following types directly support the gzip compression case: - `Pending` is a non-blocking constructor for a `Decoder` in case the body needs to be checked for EOF */ -use std::fmt; -use std::mem; use std::cmp; +use std::fmt; use std::io::{self, Read}; +use std::mem; use bytes::{Buf, BufMut, BytesMut}; use flate2::read::GzDecoder; use futures::{Async, Future, Poll, Stream}; -use hyper::{HeaderMap}; use hyper::header::{CONTENT_ENCODING, CONTENT_LENGTH, TRANSFER_ENCODING}; +use hyper::HeaderMap; -use log::{warn}; +use log::warn; use super::{Body, Chunk}; use crate::error; @@ -42,7 +42,7 @@ const INIT_BUFFER_SIZE: usize = 8192; /// /// The inner decoder may be constructed asynchronously. pub struct Decoder { - inner: Inner + inner: Inner, } enum Inner { @@ -51,7 +51,7 @@ enum Inner { /// A `Gzip` decoder will uncompress the gzipped response content before returning it. Gzip(Gzip), /// A decoder that doesn't have a value yet. - Pending(Pending) + Pending(Pending), } /// A future attempt to poll the response body for EOF so we know whether to use gzip or not. @@ -68,8 +68,7 @@ struct Gzip { impl fmt::Debug for Decoder { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Decoder") - .finish() + f.debug_struct("Decoder").finish() } } @@ -80,7 +79,7 @@ impl Decoder { #[inline] pub fn empty() -> Decoder { Decoder { - inner: Inner::PlainText(Body::empty()) + inner: Inner::PlainText(Body::empty()), } } @@ -90,7 +89,7 @@ impl Decoder { #[inline] fn plain_text(body: Body) -> Decoder { Decoder { - inner: Inner::PlainText(body) + inner: Inner::PlainText(body), } } @@ -100,7 +99,9 @@ impl Decoder { #[inline] fn gzip(body: Body) -> Decoder { Decoder { - inner: Inner::Pending(Pending { body: ReadableChunks::new(body) }) + inner: Inner::Pending(Pending { + body: ReadableChunks::new(body), + }), } } @@ -120,11 +121,11 @@ impl Decoder { .get_all(CONTENT_ENCODING) .iter() .any(|enc| enc == "gzip"); - content_encoding_gzip || - headers - .get_all(TRANSFER_ENCODING) - .iter() - .any(|enc| enc == "gzip") + content_encoding_gzip + || headers + .get_all(TRANSFER_ENCODING) + .iter() + .any(|enc| enc == "gzip") }; if is_gzip { if let Some(content_length) = headers.get(CONTENT_LENGTH) { @@ -153,15 +154,13 @@ impl Stream for Decoder { fn poll(&mut self) -> Poll, Self::Error> { // Do a read or poll for a pendidng decoder value. let new_value = match self.inner { - Inner::Pending(ref mut future) => { - match future.poll() { - Ok(Async::Ready(inner)) => inner, - Ok(Async::NotReady) => return Ok(Async::NotReady), - Err(e) => return Err(e) - } + Inner::Pending(ref mut future) => match future.poll() { + Ok(Async::Ready(inner)) => inner, + Ok(Async::NotReady) => return Ok(Async::NotReady), + Err(e) => return Err(e), }, Inner::PlainText(ref mut body) => return body.poll(), - Inner::Gzip(ref mut decoder) => return decoder.poll() + Inner::Gzip(ref mut decoder) => return decoder.poll(), }; self.inner = new_value; @@ -177,13 +176,13 @@ impl Future for Pending { let body_state = match self.body.poll_stream() { Ok(Async::Ready(state)) => state, Ok(Async::NotReady) => return Ok(Async::NotReady), - Err(e) => return Err(e) + Err(e) => return Err(e), }; let body = mem::replace(&mut self.body, ReadableChunks::new(Body::empty())); match body_state { StreamState::Eof => Ok(Async::Ready(Inner::PlainText(Body::empty()))), - StreamState::HasMore => Ok(Async::Ready(Inner::Gzip(Gzip::new(body)))) + StreamState::HasMore => Ok(Async::Ready(Inner::Gzip(Gzip::new(body)))), } } } @@ -258,7 +257,7 @@ enum StreamState { /// More bytes can be read from the stream. HasMore, /// No more bytes can be read from the stream. - Eof + Eof, } impl ReadableChunks { @@ -273,8 +272,7 @@ impl ReadableChunks { impl fmt::Debug for ReadableChunks { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("ReadableChunks") - .finish() + f.debug_struct("ReadableChunks").finish() } } @@ -296,20 +294,12 @@ where } else { return Ok(len); } - }, - ReadState::NotReady => { - match self.poll_stream() { - Ok(Async::Ready(StreamState::HasMore)) => continue, - Ok(Async::Ready(StreamState::Eof)) => { - return Ok(0) - }, - Ok(Async::NotReady) => { - return Err(io::ErrorKind::WouldBlock.into()) - }, - Err(e) => { - return Err(error::into_io(e)) - } - } + } + ReadState::NotReady => match self.poll_stream() { + Ok(Async::Ready(StreamState::HasMore)) => continue, + Ok(Async::Ready(StreamState::Eof)) => return Ok(0), + Ok(Async::NotReady) => return Err(io::ErrorKind::WouldBlock.into()), + Err(e) => return Err(error::into_io(e)), }, ReadState::Eof => return Ok(0), } @@ -320,7 +310,8 @@ where } impl ReadableChunks - where S: Stream +where + S: Stream, { /// Poll the readiness of the inner reader. /// @@ -332,16 +323,14 @@ impl ReadableChunks self.state = ReadState::Ready(chunk); Ok(Async::Ready(StreamState::HasMore)) - }, + } Ok(Async::Ready(None)) => { self.state = ReadState::Eof; Ok(Async::Ready(StreamState::Eof)) - }, - Ok(Async::NotReady) => { - Ok(Async::NotReady) - }, - Err(e) => Err(e) + } + Ok(Async::NotReady) => Ok(Async::NotReady), + Err(e) => Err(e), } } } diff --git a/src/async_impl/multipart.rs b/src/async_impl/multipart.rs index fece365..dfb06a1 100644 --- a/src/async_impl/multipart.rs +++ b/src/async_impl/multipart.rs @@ -2,10 +2,10 @@ use std::borrow::Cow; use std::fmt; +use http::HeaderMap; use mime_guess::Mime; use url::percent_encoding::{self, EncodeSet, PATH_SEGMENT_ENCODE_SET}; use uuid::Uuid; -use http::HeaderMap; use futures::Stream; @@ -98,7 +98,7 @@ impl Form { /// Consume this instance and transform into an instance of hyper::Body for use in a request. pub(crate) fn stream(mut self) -> hyper::Body { - if self.inner.fields.is_empty(){ + if self.inner.fields.is_empty() { return hyper::Body::empty(); } @@ -117,7 +117,7 @@ impl Form { hyper::Body::wrap_stream(stream.chain(last)) } - /// Generate a hyper::Body stream for a single Part instance of a Form request. + /// Generate a hyper::Body stream for a single Part instance of a Form request. pub(crate) fn part_stream(&mut self, name: T, part: Part) -> hyper::Body where T: Into>, @@ -126,12 +126,20 @@ impl Form { let boundary = hyper::Body::from(format!("--{}\r\n", self.boundary())); // append headers let header = hyper::Body::from({ - let mut h = self.inner.percent_encoding.encode_headers(&name.into(), &part.meta); + let mut h = self + .inner + .percent_encoding + .encode_headers(&name.into(), &part.meta); h.extend_from_slice(b"\r\n\r\n"); h }); // then append form data followed by terminating CRLF - hyper::Body::wrap_stream(boundary.chain(header).chain(hyper::Body::wrap_stream(part.value)).chain(hyper::Body::from("\r\n".to_owned()))) + hyper::Body::wrap_stream( + boundary + .chain(header) + .chain(hyper::Body::wrap_stream(part.value)) + .chain(hyper::Body::from("\r\n".to_owned())), + ) } pub(crate) fn compute_length(&mut self) -> Option { @@ -188,7 +196,9 @@ impl Part { T::Item: Into, T::Error: std::error::Error + Send + Sync, { - Part::new(Body::wrap(hyper::Body::wrap_stream(value.map(|chunk| chunk.into())))) + Part::new(Body::wrap(hyper::Body::wrap_stream( + value.map(|chunk| chunk.into()), + ))) } fn new(value: Body) -> Part { @@ -306,7 +316,13 @@ impl FormParts

{ // in Reader. Not the cleanest solution because if that format string is // ever changed then this formula needs to be changed too which is not an // obvious dependency in the code. - length += 2 + self.boundary().len() as u64 + 2 + header_length as u64 + 4 + value_length + 2 + length += 2 + + self.boundary().len() as u64 + + 2 + + header_length as u64 + + 4 + + value_length + + 2 } _ => return None, } @@ -340,7 +356,7 @@ impl PartMetadata { PartMetadata { mime: None, file_name: None, - headers: HeaderMap::default() + headers: HeaderMap::default(), } } @@ -358,11 +374,10 @@ impl PartMetadata { } } - impl PartMetadata { pub(crate) fn fmt_fields<'f, 'fa, 'fb>( &self, - debug_struct: &'f mut fmt::DebugStruct<'fa, 'fb> + debug_struct: &'f mut fmt::DebugStruct<'fa, 'fb>, ) -> &'f mut fmt::DebugStruct<'fa, 'fb> { debug_struct .field("mime", &self.mime) @@ -377,22 +392,24 @@ pub(crate) struct AttrCharEncodeSet; impl EncodeSet for AttrCharEncodeSet { fn contains(&self, ch: u8) -> bool { match ch as char { - '!' => false, - '#' => false, - '$' => false, - '&' => false, - '+' => false, - '-' => false, - '.' => false, - '^' => false, - '_' => false, - '`' => false, - '|' => false, - '~' => false, - _ => { - let is_alpha_numeric = ch >= 0x41 && ch <= 0x5a || ch >= 0x61 && ch <= 0x7a || ch >= 0x30 && ch <= 0x39; - !is_alpha_numeric - } + '!' => false, + '#' => false, + '$' => false, + '&' => false, + '+' => false, + '-' => false, + '.' => false, + '^' => false, + '_' => false, + '`' => false, + '|' => false, + '~' => false, + _ => { + let is_alpha_numeric = ch >= 0x41 && ch <= 0x5a + || ch >= 0x61 && ch <= 0x7a + || ch >= 0x30 && ch <= 0x39; + !is_alpha_numeric + } } } } @@ -417,36 +434,38 @@ impl PercentEncoding { None => "".to_string(), }, ); - field.headers.iter().fold(s.into_bytes(), |mut header, (k,v)| { - header.extend_from_slice(b"\r\n"); - header.extend_from_slice(k.as_str().as_bytes()); - header.extend_from_slice(b": "); - header.extend_from_slice(v.as_bytes()); - header - }) + field + .headers + .iter() + .fold(s.into_bytes(), |mut header, (k, v)| { + header.extend_from_slice(b"\r\n"); + header.extend_from_slice(k.as_str().as_bytes()); + header.extend_from_slice(b": "); + header.extend_from_slice(v.as_bytes()); + header + }) } // According to RFC7578 Section 4.2, `filename*=` syntax is invalid. // See https://github.com/seanmonstar/reqwest/issues/419. fn format_filename(&self, filename: &str) -> String { - let legal_filename = filename.replace("\\", "\\\\") - .replace("\"", "\\\"") - .replace("\r", "\\\r") - .replace("\n", "\\\n"); + let legal_filename = filename + .replace("\\", "\\\\") + .replace("\"", "\\\"") + .replace("\r", "\\\r") + .replace("\n", "\\\n"); format!("filename=\"{}\"", legal_filename) } fn format_parameter(&self, name: &str, value: &str) -> String { let legal_value = match *self { PercentEncoding::PathSegment => { - percent_encoding::utf8_percent_encode(value, PATH_SEGMENT_ENCODE_SET) - .to_string() - }, + percent_encoding::utf8_percent_encode(value, PATH_SEGMENT_ENCODE_SET).to_string() + } PercentEncoding::AttrChar => { - percent_encoding::utf8_percent_encode(value, AttrCharEncodeSet) - .to_string() - }, - PercentEncoding::NoOp => { value.to_string() }, + percent_encoding::utf8_percent_encode(value, AttrCharEncodeSet).to_string() + } + PercentEncoding::NoOp => value.to_string(), }; if value.len() == legal_value.len() { // nothing has been percent encoded @@ -477,38 +496,45 @@ mod tests { #[test] fn stream_to_end() { let mut form = Form::new() - .part("reader1", Part::stream(futures::stream::once::<_, hyper::Error>(Ok(Chunk::from("part1".to_owned()))))) - .part("key1", Part::text("value1")) .part( - "key2", - Part::text("value2").mime(mime::IMAGE_BMP), + "reader1", + Part::stream(futures::stream::once::<_, hyper::Error>(Ok(Chunk::from( + "part1".to_owned(), + )))), ) - .part("reader2", Part::stream(futures::stream::once::<_, hyper::Error>(Ok(Chunk::from("part2".to_owned()))))) + .part("key1", Part::text("value1")) + .part("key2", Part::text("value2").mime(mime::IMAGE_BMP)) .part( - "key3", - Part::text("value3").file_name("filename"), - ); + "reader2", + Part::stream(futures::stream::once::<_, hyper::Error>(Ok(Chunk::from( + "part2".to_owned(), + )))), + ) + .part("key3", Part::text("value3").file_name("filename")); form.inner.boundary = "boundary".to_string(); - let expected = "--boundary\r\n\ - Content-Disposition: form-data; name=\"reader1\"\r\n\r\n\ - part1\r\n\ - --boundary\r\n\ - Content-Disposition: form-data; name=\"key1\"\r\n\r\n\ - value1\r\n\ - --boundary\r\n\ - Content-Disposition: form-data; name=\"key2\"\r\n\ - Content-Type: image/bmp\r\n\r\n\ - value2\r\n\ - --boundary\r\n\ - Content-Disposition: form-data; name=\"reader2\"\r\n\r\n\ - part2\r\n\ - --boundary\r\n\ - Content-Disposition: form-data; name=\"key3\"; filename=\"filename\"\r\n\r\n\ - value3\r\n--boundary--\r\n"; + let expected = + "--boundary\r\n\ + Content-Disposition: form-data; name=\"reader1\"\r\n\r\n\ + part1\r\n\ + --boundary\r\n\ + Content-Disposition: form-data; name=\"key1\"\r\n\r\n\ + value1\r\n\ + --boundary\r\n\ + Content-Disposition: form-data; name=\"key2\"\r\n\ + Content-Type: image/bmp\r\n\r\n\ + value2\r\n\ + --boundary\r\n\ + Content-Disposition: form-data; name=\"reader2\"\r\n\r\n\ + part2\r\n\ + --boundary\r\n\ + Content-Disposition: form-data; name=\"key3\"; filename=\"filename\"\r\n\r\n\ + value3\r\n--boundary--\r\n"; let mut rt = tokio::runtime::current_thread::Runtime::new().expect("new rt"); let body_ft = form.stream(); - let out = rt.block_on(body_ft.map(|c| c.into_bytes()).concat2()).unwrap(); + let out = rt + .block_on(body_ft.map(|c| c.into_bytes()).concat2()) + .unwrap(); // These prints are for debug purposes in case the test fails println!( "START REAL\n{}\nEND REAL", @@ -534,7 +560,9 @@ mod tests { let mut rt = tokio::runtime::current_thread::Runtime::new().expect("new rt"); let body_ft = form.stream(); - let out = rt.block_on(body_ft.map(|c| c.into_bytes()).concat2()).unwrap(); + let out = rt + .block_on(body_ft.map(|c| c.into_bytes()).concat2()) + .unwrap(); // These prints are for debug purposes in case the test fails println!( "START REAL\n{}\nEND REAL", diff --git a/src/async_impl/request.rs b/src/async_impl/request.rs index a8e3c7b..b77e6ba 100644 --- a/src/async_impl/request.rs +++ b/src/async_impl/request.rs @@ -1,18 +1,18 @@ use std::fmt; -use base64::{encode}; +use base64::encode; use futures::Future; use serde::Serialize; use serde_json; use serde_urlencoded; -use super::body::{Body}; +use super::body::Body; use super::client::{Client, Pending}; use super::multipart; use super::response::Response; -use crate::header::{CONTENT_LENGTH, CONTENT_TYPE, HeaderMap, HeaderName, HeaderValue}; -use http::HttpTryFrom; +use crate::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_LENGTH, CONTENT_TYPE}; use crate::{Method, Url}; +use http::HttpTryFrom; /// A request which can be executed with `Client::execute()`. pub struct Request { @@ -95,10 +95,7 @@ impl Request { impl RequestBuilder { pub(super) fn new(client: Client, request: crate::Result) -> RequestBuilder { - RequestBuilder { - client, - request, - } + RequestBuilder { client, request } } /// Add a `Header` to this Request. @@ -110,11 +107,11 @@ impl RequestBuilder { let mut error = None; if let Ok(ref mut req) = self.request { match >::try_from(key) { - Ok(key) => { - match >::try_from(value) { - Ok(value) => { req.headers_mut().append(key, value); } - Err(e) => error = Some(crate::error::from(e.into())), + Ok(key) => match >::try_from(value) { + Ok(value) => { + req.headers_mut().append(key, value); } + Err(e) => error = Some(crate::error::from(e.into())), }, Err(e) => error = Some(crate::error::from(e.into())), }; @@ -168,7 +165,7 @@ impl RequestBuilder { { let auth = match password { Some(password) => format!("{}:{}", username, password), - None => format!("{}:", username) + None => format!("{}:", username), }; let header_value = format!("Basic {}", encode(&auth)); self.header(crate::header::AUTHORIZATION, &*header_value) @@ -221,10 +218,7 @@ impl RequestBuilder { pub fn multipart(self, mut multipart: multipart::Form) -> RequestBuilder { let mut builder = self.header( CONTENT_TYPE, - format!( - "multipart/form-data; boundary={}", - multipart.boundary() - ).as_str() + format!("multipart/form-data; boundary={}", multipart.boundary()).as_str(), ); builder = match multipart.compute_length() { @@ -286,10 +280,10 @@ impl RequestBuilder { Ok(body) => { req.headers_mut().insert( CONTENT_TYPE, - HeaderValue::from_static("application/x-www-form-urlencoded") + HeaderValue::from_static("application/x-www-form-urlencoded"), ); *req.body_mut() = Some(body.into()); - }, + } Err(err) => error = Some(crate::error::from(err)), } } @@ -310,12 +304,10 @@ impl RequestBuilder { if let Ok(ref mut req) = self.request { match serde_json::to_vec(json) { Ok(body) => { - req.headers_mut().insert( - CONTENT_TYPE, - HeaderValue::from_static("application/json") - ); + req.headers_mut() + .insert(CONTENT_TYPE, HeaderValue::from_static("application/json")); *req.body_mut() = Some(body.into()); - }, + } Err(err) => error = Some(crate::error::from(err)), } } @@ -368,8 +360,7 @@ impl RequestBuilder { impl fmt::Debug for Request { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt_request_fields(&mut f.debug_struct("Request"), self) - .finish() + fmt_request_fields(&mut f.debug_struct("Request"), self).finish() } } @@ -377,27 +368,22 @@ impl fmt::Debug for RequestBuilder { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut builder = f.debug_struct("RequestBuilder"); match self.request { - Ok(ref req) => { - fmt_request_fields(&mut builder, req) - .finish() - }, - Err(ref err) => { - builder - .field("error", err) - .finish() - } + Ok(ref req) => fmt_request_fields(&mut builder, req).finish(), + Err(ref err) => builder.field("error", err).finish(), } } } -fn fmt_request_fields<'a, 'b>(f: &'a mut fmt::DebugStruct<'a, 'b>, req: &Request) -> &'a mut fmt::DebugStruct<'a, 'b> { +fn fmt_request_fields<'a, 'b>( + f: &'a mut fmt::DebugStruct<'a, 'b>, + req: &Request, +) -> &'a mut fmt::DebugStruct<'a, 'b> { f.field("method", &req.method) .field("url", &req.url) .field("headers", &req.headers) } pub(crate) fn replace_headers(dst: &mut HeaderMap, src: HeaderMap) { - // IntoIter of HeaderMap yields (Option, HeaderValue). // The first time a name is yielded, it will be Some(name), and if // there are more values with the same name, the next yield will be @@ -413,11 +399,11 @@ pub(crate) fn replace_headers(dst: &mut HeaderMap, src: HeaderMap) { Some(key) => { dst.insert(key.clone(), value); prev_name = Some(key); - }, + } None => match prev_name { Some(ref key) => { dst.append(key.clone(), value); - }, + } None => unreachable!("HeaderMap::into_iter yielded None first"), }, } @@ -427,8 +413,8 @@ pub(crate) fn replace_headers(dst: &mut HeaderMap, src: HeaderMap) { #[cfg(test)] mod tests { use super::Client; - use std::collections::BTreeMap; use serde::Serialize; + use std::collections::BTreeMap; #[test] fn add_query_append() { @@ -467,7 +453,10 @@ mod tests { let some_url = "https://google.com/"; let r = client.get(some_url); - let params = Params { foo: "bar".into(), qux: 3 }; + let params = Params { + foo: "bar".into(), + qux: 3, + }; let r = r.query(¶ms); @@ -510,11 +499,7 @@ mod tests { assert_eq!(req.headers()["im-a"], "keeper"); - let foo = req - .headers() - .get_all("foo") - .iter() - .collect::>(); + let foo = req.headers().get_all("foo").iter().collect::>(); assert_eq!(foo.len(), 2); assert_eq!(foo[0], "bar"); assert_eq!(foo[1], "baz"); diff --git a/src/async_impl/response.rs b/src/async_impl/response.rs index 481213a..007595b 100644 --- a/src/async_impl/response.rs +++ b/src/async_impl/response.rs @@ -1,28 +1,26 @@ -use std::fmt; -use std::mem; -use std::marker::PhantomData; -use std::net::SocketAddr; use std::borrow::Cow; +use std::fmt; +use std::marker::PhantomData; +use std::mem; +use std::net::SocketAddr; use encoding_rs::{Encoding, UTF_8}; -use futures::{Async, Future, Poll, Stream, try_ready}; use futures::stream::Concat2; +use futures::{try_ready, Async, Future, Poll, Stream}; use http; -use hyper::{HeaderMap, StatusCode, Version}; use hyper::client::connect::HttpInfo; -use hyper::header::{CONTENT_LENGTH}; +use hyper::header::CONTENT_LENGTH; +use hyper::{HeaderMap, StatusCode, Version}; +use log::debug; use mime::Mime; -use tokio::timer::Delay; use serde::de::DeserializeOwned; use serde_json; +use tokio::timer::Delay; use url::Url; -use log::{debug}; - -use crate::cookie; -use super::Decoder; use super::body::Body; - +use super::Decoder; +use crate::cookie; /// A Response to a submitted `Request`. pub struct Response { @@ -37,7 +35,12 @@ pub struct Response { } impl Response { - pub(super) fn new(res: hyper::Response, url: Url, gzip: bool, timeout: Option) -> Response { + pub(super) fn new( + res: hyper::Response, + url: Url, + gzip: bool, + timeout: Option, + ) -> Response { let (parts, body) = res.into_parts(); let status = parts.status; let version = parts.version; @@ -57,7 +60,6 @@ impl Response { } } - /// Get the `StatusCode` of this `Response`. #[inline] pub fn status(&self) -> StatusCode { @@ -77,11 +79,10 @@ impl Response { } /// Retrieve the cookies contained in the response. - /// + /// /// Note that invalid 'Set-Cookie' headers will be ignored. pub fn cookies<'a>(&'a self) -> impl Iterator> + 'a { - cookie::extract_response_cookies(&self.headers) - .filter_map(Result::ok) + cookie::extract_response_cookies(&self.headers).filter_map(Result::ok) } /// Get the final `Url` of this `Response`. @@ -92,8 +93,7 @@ impl Response { /// Get the remote address used to get this `Response`. pub fn remote_addr(&self) -> Option { - self - .extensions + self.extensions .get::() .map(|info| info.remote_addr()) } @@ -106,8 +106,7 @@ impl Response { /// - The response is gzipped and automatically decoded (thus changing /// the actual decoded length). pub fn content_length(&self) -> Option { - self - .headers() + self.headers() .get(CONTENT_LENGTH) .and_then(|ct_len| ct_len.to_str().ok()) .and_then(|ct_len| ct_len.parse().ok()) @@ -145,27 +144,24 @@ impl Response { } /// Get the response text given a specific encoding - pub fn text_with_charset(&mut self, default_encoding: &str) -> impl Future { + pub fn text_with_charset( + &mut self, + default_encoding: &str, + ) -> impl Future { let body = mem::replace(&mut self.body, Decoder::empty()); - let content_type = self.headers.get(crate::header::CONTENT_TYPE) - .and_then(|value| { - value.to_str().ok() - }) - .and_then(|value| { - value.parse::().ok() - }); + let content_type = self + .headers + .get(crate::header::CONTENT_TYPE) + .and_then(|value| value.to_str().ok()) + .and_then(|value| value.parse::().ok()); let encoding_name = content_type .as_ref() - .and_then(|mime| { - mime - .get_param("charset") - .map(|charset| charset.as_str()) - }) + .and_then(|mime| mime.get_param("charset").map(|charset| charset.as_str())) .unwrap_or(default_encoding); let encoding = Encoding::for_label(encoding_name.as_bytes()).unwrap_or(UTF_8); Text { concat: body.concat2(), - encoding + encoding, } } @@ -256,7 +252,8 @@ impl> From> for Response { let (mut parts, body) = r.into_parts(); let body = body.into(); let body = Decoder::detect(&mut parts.headers, body, false); - let url = parts.extensions + let url = parts + .extensions .remove::() .unwrap_or_else(|| ResponseUrl(Url::parse("http://no.url.provided.local").unwrap())); let url = url.0; @@ -289,8 +286,7 @@ impl Future for Json { impl fmt::Debug for Json { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Json") - .finish() + f.debug_struct("Json").finish() } } @@ -308,7 +304,9 @@ impl Future for Text { // a block because of borrow checker { let (text, _, _) = self.encoding.decode(&bytes); - if let Cow::Owned(s) = text { return Ok(Async::Ready(s)) } + if let Cow::Owned(s) = text { + return Ok(Async::Ready(s)); + } } unsafe { // decoding returned Cow::Borrowed, meaning these bytes @@ -357,9 +355,9 @@ impl ResponseBuilderExt for http::response::Builder { #[cfg(test)] mod tests { - use url::Url; + use super::{Response, ResponseBuilderExt, ResponseUrl}; use http::response::Builder; - use super::{Response, ResponseUrl, ResponseBuilderExt}; + use url::Url; #[test] fn test_response_builder_ext() { @@ -370,7 +368,10 @@ mod tests { .body(()) .unwrap(); - assert_eq!(response.extensions().get::(), Some(&ResponseUrl(url))); + assert_eq!( + response.extensions().get::(), + Some(&ResponseUrl(url)) + ); } #[test] diff --git a/src/body.rs b/src/body.rs index 87e36eb..bea52e5 100644 --- a/src/body.rs +++ b/src/body.rs @@ -1,12 +1,12 @@ -use std::fs::File; use std::fmt; +use std::fs::File; use std::io::{self, Cursor, Read}; use bytes::Bytes; -use futures::{Future, try_ready}; +use futures::{try_ready, Future}; use hyper::{self}; -use crate::{async_impl}; +use crate::async_impl; /// The body of a `Request`. /// @@ -102,7 +102,7 @@ impl Body { tx, }; (Some(tx), async_impl::Body::wrap(rx), len) - }, + } Kind::Bytes(chunk) => { let len = chunk.len() as u64; (None, async_impl::Body::reusable(chunk), Some(len)) @@ -111,12 +111,10 @@ impl Body { } pub(crate) fn try_clone(&self) -> Option { - self.kind.try_clone() - .map(|kind| Body { kind }) + self.kind.try_clone().map(|kind| Body { kind }) } } - enum Kind { Reader(Box, Option), Bytes(Bytes), @@ -147,7 +145,6 @@ impl From for Body { } } - impl From<&'static [u8]> for Body { #[inline] fn from(s: &'static [u8]) -> Body { @@ -177,7 +174,8 @@ impl From for Body { impl fmt::Debug for Kind { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Kind::Reader(_, ref v) => f.debug_struct("Reader") + Kind::Reader(_, ref v) => f + .debug_struct("Reader") .field("length", &DebugLength(v)) .finish(), Kind::Bytes(ref v) => fmt::Debug::fmt(v, f), @@ -218,10 +216,10 @@ pub(crate) struct Sender { impl Sender { // A `Future` that may do blocking read calls. // As a `Future`, this integrates easily with `wait::timeout`. - pub(crate) fn send(self) -> impl Future { - use std::cmp; + pub(crate) fn send(self) -> impl Future { use bytes::{BufMut, BytesMut}; use futures::future; + use std::cmp; let con_len = self.body.1; let cap = cmp::min(self.body.1.unwrap_or(8192), 8192); @@ -261,15 +259,12 @@ impl Sender { // read. Return. return Ok(().into()); } - Ok(n) => { - unsafe { buf.advance_mut(n); } - } + Ok(n) => unsafe { + buf.advance_mut(n); + }, Err(e) => { let ret = io::Error::new(e.kind(), e.to_string()); - tx - .take() - .expect("tx only taken on error") - .abort(); + tx.take().expect("tx only taken on error").abort(); return Err(crate::error::from(ret)); } } @@ -297,8 +292,8 @@ impl Sender { pub(crate) fn read_to_string(mut body: Body) -> io::Result { let mut s = String::new(); match body.kind { - Kind::Reader(ref mut reader, _) => reader.read_to_string(&mut s), - Kind::Bytes(ref mut bytes) => (&**bytes).read_to_string(&mut s), - } - .map(|_| s) + Kind::Reader(ref mut reader, _) => reader.read_to_string(&mut s), + Kind::Bytes(ref mut bytes) => (&**bytes).read_to_string(&mut s), + } + .map(|_| s) } diff --git a/src/client.rs b/src/client.rs index 9a96296..9e9d5a2 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,18 +1,18 @@ use std::fmt; -use std::sync::Arc; -use std::time::Duration; -use std::thread; use std::net::IpAddr; +use std::sync::Arc; +use std::thread; +use std::time::Duration; -use futures::{Async, Future, Stream}; use futures::future::{self, Either}; use futures::sync::{mpsc, oneshot}; +use futures::{Async, Future, Stream}; -use log::{trace}; +use log::trace; use crate::request::{Request, RequestBuilder}; use crate::response::Response; -use crate::{async_impl, header, Method, IntoUrl, Proxy, RedirectPolicy, wait}; +use crate::{async_impl, header, wait, IntoUrl, Method, Proxy, RedirectPolicy}; #[cfg(feature = "tls")] use crate::{Certificate, Identity}; @@ -81,9 +81,7 @@ impl ClientBuilder { /// This method fails if TLS backend cannot be initialized, or the resolver /// cannot load the system configuration. pub fn build(self) -> crate::Result { - ClientHandle::new(self).map(|handle| Client { - inner: handle, - }) + ClientHandle::new(self).map(|handle| Client { inner: handle }) } /// Disable proxy setting. @@ -184,7 +182,6 @@ impl ClientBuilder { self.with_inner(move |inner| inner.identity(identity)) } - /// Controls the use of hostname verification. /// /// Defaults to `false`. @@ -399,7 +396,6 @@ impl ClientBuilder { } } - impl Client { /// Constructs a new `Client`. /// @@ -411,9 +407,7 @@ impl Client { /// Use `Client::builder()` if you wish to handle the failure as an `Error` /// instead of panicking. pub fn new() -> Client { - ClientBuilder::new() - .build() - .expect("Client::new()") + ClientBuilder::new().build().expect("Client::new()") } /// Creates a `ClientBuilder` to configure a `Client`. @@ -486,9 +480,7 @@ impl Client { /// /// This method fails whenever supplied `Url` cannot be parsed. pub fn request(&self, method: Method, url: U) -> RequestBuilder { - let req = url - .into_url() - .map(move |url| Request::new(method, url)); + let req = url.into_url().map(move |url| Request::new(method, url)); RequestBuilder::new(self.clone(), req) } @@ -521,22 +513,24 @@ impl fmt::Debug for Client { impl fmt::Debug for ClientBuilder { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("ClientBuilder") - .finish() + f.debug_struct("ClientBuilder").finish() } } #[derive(Clone)] struct ClientHandle { timeout: Timeout, - inner: Arc + inner: Arc, } -type ThreadSender = mpsc::UnboundedSender<(async_impl::Request, oneshot::Sender>)>; +type ThreadSender = mpsc::UnboundedSender<( + async_impl::Request, + oneshot::Sender>, +)>; struct InnerClientHandle { tx: Option, - thread: Option> + thread: Option>, } impl Drop for InnerClientHandle { @@ -552,66 +546,64 @@ impl ClientHandle { let builder = builder.inner; let (tx, rx) = mpsc::unbounded(); let (spawn_tx, spawn_rx) = oneshot::channel::>(); - let handle = try_!(thread::Builder::new().name("reqwest-internal-sync-runtime".into()).spawn(move || { - use tokio::runtime::current_thread::Runtime; + let handle = try_!(thread::Builder::new() + .name("reqwest-internal-sync-runtime".into()) + .spawn(move || { + use tokio::runtime::current_thread::Runtime; - let built = (|| { - let rt = try_!(Runtime::new()); - let client = builder.build()?; - Ok((rt, client)) - })(); + let built = (|| { + let rt = try_!(Runtime::new()); + let client = builder.build()?; + Ok((rt, client)) + })(); - let (mut rt, client) = match built { - Ok((rt, c)) => { - if spawn_tx.send(Ok(())).is_err() { + let (mut rt, client) = match built { + Ok((rt, c)) => { + if spawn_tx.send(Ok(())).is_err() { + return; + } + (rt, c) + } + Err(e) => { + let _ = spawn_tx.send(Err(e)); return; } - (rt, c) - }, - Err(e) => { - let _ = spawn_tx.send(Err(e)); - return; - } - }; + }; - let work = rx.for_each(move |(req, tx)| { - let mut tx_opt: Option>> = Some(tx); - let mut res_fut = client.execute(req); + let work = rx.for_each(move |(req, tx)| { + let mut tx_opt: Option>> = + Some(tx); + let mut res_fut = client.execute(req); - let task = future::poll_fn(move || { - let canceled = tx_opt - .as_mut() - .expect("polled after complete") - .poll_cancel() - .expect("poll_cancel cannot error") - .is_ready(); - - if canceled { - trace!("response receiver is canceled"); - Ok(Async::Ready(())) - } else { - let result = match res_fut.poll() { - Ok(Async::NotReady) => return Ok(Async::NotReady), - Ok(Async::Ready(res)) => Ok(res), - Err(err) => Err(err), - }; - - let _ = tx_opt - .take() + let task = future::poll_fn(move || { + let canceled = tx_opt + .as_mut() .expect("polled after complete") - .send(result); - Ok(Async::Ready(())) - } + .poll_cancel() + .expect("poll_cancel cannot error") + .is_ready(); + + if canceled { + trace!("response receiver is canceled"); + Ok(Async::Ready(())) + } else { + let result = match res_fut.poll() { + Ok(Async::NotReady) => return Ok(Async::NotReady), + Ok(Async::Ready(res)) => Ok(res), + Err(err) => Err(err), + }; + + let _ = tx_opt.take().expect("polled after complete").send(result); + Ok(Async::Ready(())) + } + }); + tokio::spawn(task); + Ok(()) }); - tokio::spawn(task); - Ok(()) - }); - - // work is Future<(), ()>, and our closure will never return Err - rt.block_on(work) - .expect("runtime unexpected error"); - })); + // work is Future<(), ()>, and our closure will never return Err + rt.block_on(work).expect("runtime unexpected error"); + })); // Wait for the runtime thread to start up... match spawn_rx.wait() { @@ -620,13 +612,11 @@ impl ClientHandle { Err(_canceled) => event_loop_panicked(), } - let inner_handle = Arc::new(InnerClientHandle { tx: Some(tx), - thread: Some(handle) + thread: Some(handle), }); - Ok(ClientHandle { timeout, inner: inner_handle, @@ -637,7 +627,8 @@ impl ClientHandle { let (tx, rx) = oneshot::channel(); let (req, body) = req.into_async(); let url = req.url().clone(); - self.inner.tx + self.inner + .tx .as_ref() .expect("core thread exited early") .unbounded_send((req, tx)) @@ -645,7 +636,7 @@ impl ClientHandle { let write = if let Some(body) = body { Either::A(body.send()) - //try_!(body.send(self.timeout.0), &url); + //try_!(body.send(self.timeout.0), &url); } else { Either::B(future::ok(())) }; @@ -657,15 +648,17 @@ impl ClientHandle { let res = match wait::timeout(fut, self.timeout.0) { Ok(res) => res, Err(wait::Waited::TimedOut) => return Err(crate::error::timedout(Some(url))), - Err(wait::Waited::Executor(err)) => { - return Err(crate::error::from(err).with_url(url)) - }, + Err(wait::Waited::Executor(err)) => return Err(crate::error::from(err).with_url(url)), Err(wait::Waited::Inner(err)) => { return Err(err.with_url(url)); - }, + } }; res.map(|res| { - Response::new(res, self.timeout.0, KeepCoreThreadAlive(Some(self.inner.clone()))) + Response::new( + res, + self.timeout.0, + KeepCoreThreadAlive(Some(self.inner.clone())), + ) }) } } diff --git a/src/connect.rs b/src/connect.rs index 5d2b9a2..8b9b9af 100644 --- a/src/connect.rs +++ b/src/connect.rs @@ -4,16 +4,16 @@ use hyper::client::connect::{Connect, Connected, Destination}; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_timer::Timeout; -#[cfg(feature = "default-tls")] -use native_tls::{TlsConnector, TlsConnectorBuilder}; -#[cfg(feature = "tls")] -use futures::Poll; #[cfg(feature = "tls")] use bytes::BufMut; +#[cfg(feature = "tls")] +use futures::Poll; +#[cfg(feature = "default-tls")] +use native_tls::{TlsConnector, TlsConnectorBuilder}; use std::io; -use std::sync::Arc; use std::net::IpAddr; +use std::sync::Arc; use std::time::Duration; #[cfg(feature = "trust-dns")] @@ -25,13 +25,12 @@ type HttpConnector = hyper::client::HttpConnector; #[cfg(not(feature = "trust-dns"))] type HttpConnector = hyper::client::HttpConnector; - pub(crate) struct Connector { inner: Inner, proxies: Arc>, timeout: Option, #[cfg(feature = "tls")] - nodelay: bool + nodelay: bool, } enum Inner { @@ -43,17 +42,20 @@ enum Inner { RustlsTls { http: HttpConnector, tls: Arc, - tls_proxy: Arc - } + tls_proxy: Arc, + }, } impl Connector { #[cfg(not(feature = "tls"))] - pub(crate) fn new(proxies: Arc>, local_addr: T, nodelay: bool) -> crate::Result + pub(crate) fn new( + proxies: Arc>, + local_addr: T, + nodelay: bool, + ) -> crate::Result where - T: Into> + T: Into>, { - let mut http = http_connector()?; http.set_local_address(local_addr.into()); http.set_nodelay(nodelay); @@ -69,9 +71,10 @@ impl Connector { tls: TlsConnectorBuilder, proxies: Arc>, local_addr: T, - nodelay: bool) -> crate::Result - where - T: Into>, + nodelay: bool, + ) -> crate::Result + where + T: Into>, { let tls = try_!(tls.build()); @@ -83,7 +86,7 @@ impl Connector { inner: Inner::DefaultTls(http, tls), proxies, timeout: None, - nodelay + nodelay, }) } @@ -92,9 +95,10 @@ impl Connector { tls: rustls::ClientConfig, proxies: Arc>, local_addr: T, - nodelay: bool) -> crate::Result - where - T: Into>, + nodelay: bool, + ) -> crate::Result + where + T: Into>, { let mut http = http_connector()?; http.set_local_address(local_addr.into()); @@ -110,10 +114,14 @@ impl Connector { }; Ok(Connector { - inner: Inner::RustlsTls { http, tls, tls_proxy }, + inner: Inner::RustlsTls { + http, + tls, + tls_proxy, + }, proxies, timeout: None, - nodelay + nodelay, }) } @@ -138,56 +146,62 @@ impl Connector { } else { Box::new($future) } - } + }; } let dns = match proxy { - ProxyScheme::Socks5 { remote_dns: false, .. } => socks::DnsResolve::Local, - ProxyScheme::Socks5 { remote_dns: true, .. } => socks::DnsResolve::Proxy, + ProxyScheme::Socks5 { + remote_dns: false, .. + } => socks::DnsResolve::Local, + ProxyScheme::Socks5 { + remote_dns: true, .. + } => socks::DnsResolve::Proxy, ProxyScheme::Http { .. } => { unreachable!("connect_socks is only called for socks proxies"); - }, + } }; - match &self.inner { #[cfg(feature = "default-tls")] - Inner::DefaultTls(_http, tls) => if dst.scheme() == "https" { - use self::native_tls_async::TlsConnectorExt; + Inner::DefaultTls(_http, tls) => { + if dst.scheme() == "https" { + use self::native_tls_async::TlsConnectorExt; - let tls = tls.clone(); - let host = dst.host().to_owned(); - let socks_connecting = socks::connect(proxy, dst, dns); - return timeout!(socks_connecting.and_then(move |(conn, connected)| { - tls.connect_async(&host, conn) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e)) - .map(move |io| (Box::new(io) as Conn, connected)) - })); - }, + let tls = tls.clone(); + let host = dst.host().to_owned(); + let socks_connecting = socks::connect(proxy, dst, dns); + return timeout!(socks_connecting.and_then(move |(conn, connected)| { + tls.connect_async(&host, conn) + .map_err(|e| io::Error::new(io::ErrorKind::Other, e)) + .map(move |io| (Box::new(io) as Conn, connected)) + })); + } + } #[cfg(feature = "rustls-tls")] - Inner::RustlsTls { tls_proxy, .. } => if dst.scheme() == "https" { - use tokio_rustls::TlsConnector as RustlsConnector; - use tokio_rustls::webpki::DNSNameRef; + Inner::RustlsTls { tls_proxy, .. } => { + if dst.scheme() == "https" { + use tokio_rustls::webpki::DNSNameRef; + use tokio_rustls::TlsConnector as RustlsConnector; - let tls = tls_proxy.clone(); - let host = dst.host().to_owned(); - let socks_connecting = socks::connect(proxy, dst, dns); - return timeout!(socks_connecting.and_then(move |(conn, connected)| { - let maybe_dnsname = DNSNameRef::try_from_ascii_str(&host) - .map(|dnsname| dnsname.to_owned()) - .map_err(|_| io::Error::new(io::ErrorKind::Other, "Invalid DNS Name")); - futures::future::result(maybe_dnsname) - .and_then(move |dnsname| { - RustlsConnector::from(tls).connect(dnsname.as_ref(), conn) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e)) - }) - .map(move |io| { - (Box::new(io) as Conn, connected) - }) - })); - }, + let tls = tls_proxy.clone(); + let host = dst.host().to_owned(); + let socks_connecting = socks::connect(proxy, dst, dns); + return timeout!(socks_connecting.and_then(move |(conn, connected)| { + let maybe_dnsname = DNSNameRef::try_from_ascii_str(&host) + .map(|dnsname| dnsname.to_owned()) + .map_err(|_| io::Error::new(io::ErrorKind::Other, "Invalid DNS Name")); + futures::future::result(maybe_dnsname) + .and_then(move |dnsname| { + RustlsConnector::from(tls) + .connect(dnsname.as_ref(), conn) + .map_err(|e| io::Error::new(io::ErrorKind::Other, e)) + }) + .map(move |io| (Box::new(io) as Conn, connected)) + })); + } + } #[cfg(not(feature = "tls"))] - Inner::Http(_) => () + Inner::Http(_) => (), } // else no TLS @@ -231,12 +245,13 @@ impl Connect for Connector { } else { Box::new($future) } - } + }; } macro_rules! connect { ( $http:expr, $dst:expr, $proxy:expr ) => { - timeout!($http.connect($dst) + timeout!($http + .connect($dst) .map(|(io, connected)| (Box::new(io) as Conn, connected.proxy($proxy)))) }; ( $dst:expr, $proxy:expr ) => { @@ -250,17 +265,16 @@ impl Connect for Connector { http.set_nodelay(nodelay || ($dst.scheme() == "https")); let http = hyper_tls::HttpsConnector::from((http, tls.clone())); - timeout!(http.connect($dst) - .and_then(move |(io, connected)| { - if let hyper_tls::MaybeHttpsStream::Https(stream) = &io { - if !nodelay { - stream.get_ref().get_ref().set_nodelay(false)?; - } + timeout!(http.connect($dst).and_then(move |(io, connected)| { + if let hyper_tls::MaybeHttpsStream::Https(stream) = &io { + if !nodelay { + stream.get_ref().get_ref().set_nodelay(false)?; } + } - Ok((Box::new(io) as Conn, connected.proxy($proxy))) - })) - }, + Ok((Box::new(io) as Conn, connected.proxy($proxy))) + })) + } #[cfg(feature = "rustls-tls")] Inner::RustlsTls { http, tls, .. } => { let mut http = http.clone(); @@ -271,17 +285,16 @@ impl Connect for Connector { http.set_nodelay(nodelay || ($dst.scheme() == "https")); let http = hyper_rustls::HttpsConnector::from((http, tls.clone())); - timeout!(http.connect($dst) - .and_then(move |(io, connected)| { - if let hyper_rustls::MaybeHttpsStream::Https(stream) = &io { - if !nodelay { - let (io, _) = stream.get_ref(); - io.set_nodelay(false)?; - } + timeout!(http.connect($dst).and_then(move |(io, connected)| { + if let hyper_rustls::MaybeHttpsStream::Https(stream) = &io { + if !nodelay { + let (io, _) = stream.get_ref(); + io.set_nodelay(false)?; } + } - Ok((Box::new(io) as Conn, connected.proxy($proxy))) - })) + Ok((Box::new(io) as Conn, connected.proxy($proxy))) + })) } } }; @@ -299,10 +312,7 @@ impl Connect for Connector { let mut ndst = dst.clone(); - let new_scheme = puri - .scheme_part() - .map(Scheme::as_str) - .unwrap_or("http"); + let new_scheme = puri.scheme_part().map(Scheme::as_str).unwrap_or("http"); ndst.set_scheme(new_scheme) .expect("proxy target scheme should be valid"); @@ -316,60 +326,81 @@ impl Connect for Connector { match &self.inner { #[cfg(feature = "default-tls")] - Inner::DefaultTls(http, tls) => if dst.scheme() == "https" { - use self::native_tls_async::TlsConnectorExt; + Inner::DefaultTls(http, tls) => { + if dst.scheme() == "https" { + use self::native_tls_async::TlsConnectorExt; - let host = dst.host().to_owned(); - let port = dst.port().unwrap_or(443); - let mut http = http.clone(); - http.set_nodelay(nodelay); - let http = hyper_tls::HttpsConnector::from((http, tls.clone())); - let tls = tls.clone(); - return timeout!(http.connect(ndst).and_then(move |(conn, connected)| { - log::trace!("tunneling HTTPS over proxy"); - tunnel(conn, host.clone(), port, auth) - .and_then(move |tunneled| { - tls.connect_async(&host, tunneled) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e)) - }) - .map(|io| (Box::new(io) as Conn, connected.proxy(true))) - })); - }, + let host = dst.host().to_owned(); + let port = dst.port().unwrap_or(443); + let mut http = http.clone(); + http.set_nodelay(nodelay); + let http = hyper_tls::HttpsConnector::from((http, tls.clone())); + let tls = tls.clone(); + return timeout!(http.connect(ndst).and_then( + move |(conn, connected)| { + log::trace!("tunneling HTTPS over proxy"); + tunnel(conn, host.clone(), port, auth) + .and_then(move |tunneled| { + tls.connect_async(&host, tunneled).map_err(|e| { + io::Error::new(io::ErrorKind::Other, e) + }) + }) + .map(|io| (Box::new(io) as Conn, connected.proxy(true))) + } + )); + } + } #[cfg(feature = "rustls-tls")] - Inner::RustlsTls { http, tls, tls_proxy } => if dst.scheme() == "https" { - use rustls::Session; - use tokio_rustls::TlsConnector as RustlsConnector; - use tokio_rustls::webpki::DNSNameRef; + Inner::RustlsTls { + http, + tls, + tls_proxy, + } => { + if dst.scheme() == "https" { + use rustls::Session; + use tokio_rustls::webpki::DNSNameRef; + use tokio_rustls::TlsConnector as RustlsConnector; - let host = dst.host().to_owned(); - let port = dst.port().unwrap_or(443); - let mut http = http.clone(); - http.set_nodelay(nodelay); - let http = hyper_rustls::HttpsConnector::from((http, tls_proxy.clone())); - let tls = tls.clone(); - return timeout!(http.connect(ndst).and_then(move |(conn, connected)| { - log::trace!("tunneling HTTPS over proxy"); - let maybe_dnsname = DNSNameRef::try_from_ascii_str(&host) - .map(|dnsname| dnsname.to_owned()) - .map_err(|_| io::Error::new(io::ErrorKind::Other, "Invalid DNS Name")); - tunnel(conn, host, port, auth) - .and_then(move |tunneled| Ok((maybe_dnsname?, tunneled))) - .and_then(move |(dnsname, tunneled)| { - RustlsConnector::from(tls).connect(dnsname.as_ref(), tunneled) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e)) - }) - .map(|io| { - let connected = if io.get_ref().1.get_alpn_protocol() == Some(b"h2") { - connected.negotiated_h2() - } else { - connected - }; - (Box::new(io) as Conn, connected.proxy(true)) - }) - })); - }, + let host = dst.host().to_owned(); + let port = dst.port().unwrap_or(443); + let mut http = http.clone(); + http.set_nodelay(nodelay); + let http = + hyper_rustls::HttpsConnector::from((http, tls_proxy.clone())); + let tls = tls.clone(); + return timeout!(http.connect(ndst).and_then( + move |(conn, connected)| { + log::trace!("tunneling HTTPS over proxy"); + let maybe_dnsname = DNSNameRef::try_from_ascii_str(&host) + .map(|dnsname| dnsname.to_owned()) + .map_err(|_| { + io::Error::new(io::ErrorKind::Other, "Invalid DNS Name") + }); + tunnel(conn, host, port, auth) + .and_then(move |tunneled| Ok((maybe_dnsname?, tunneled))) + .and_then(move |(dnsname, tunneled)| { + RustlsConnector::from(tls) + .connect(dnsname.as_ref(), tunneled) + .map_err(|e| { + io::Error::new(io::ErrorKind::Other, e) + }) + }) + .map(|io| { + let connected = if io.get_ref().1.get_alpn_protocol() + == Some(b"h2") + { + connected.negotiated_h2() + } else { + connected + }; + (Box::new(io) as Conn, connected.proxy(true)) + }) + } + )); + } + } #[cfg(not(feature = "tls"))] - Inner::Http(_) => () + Inner::Http(_) => (), } return connect!(ndst, true); @@ -384,21 +415,30 @@ pub(crate) trait AsyncConn: AsyncRead + AsyncWrite {} impl AsyncConn for T {} pub(crate) type Conn = Box; -pub(crate) type Connecting = Box + Send>; +pub(crate) type Connecting = Box + Send>; #[cfg(feature = "tls")] -fn tunnel(conn: T, host: String, port: u16, auth: Option) -> Tunnel { - let mut buf = format!("\ - CONNECT {0}:{1} HTTP/1.1\r\n\ - Host: {0}:{1}\r\n\ - ", host, port).into_bytes(); +fn tunnel( + conn: T, + host: String, + port: u16, + auth: Option, +) -> Tunnel { + let mut buf = format!( + "\ + CONNECT {0}:{1} HTTP/1.1\r\n\ + Host: {0}:{1}\r\n\ + ", + host, port + ) + .into_bytes(); - if let Some(value) = auth { - log::debug!("tunnel to {}:{} using basic auth", host, port); - buf.extend_from_slice(b"Proxy-Authorization: "); - buf.extend_from_slice(value.as_bytes()); - buf.extend_from_slice(b"\r\n"); - } + if let Some(value) = auth { + log::debug!("tunnel to {}:{} using basic auth", host, port); + buf.extend_from_slice(b"Proxy-Authorization: "); + buf.extend_from_slice(value.as_bytes()); + buf.extend_from_slice(b"\r\n"); + } // headers end buf.extend_from_slice(b"\r\n"); @@ -420,7 +460,7 @@ struct Tunnel { #[cfg(feature = "tls")] enum TunnelState { Writing, - Reading + Reading, } #[cfg(feature = "tls")] @@ -442,7 +482,11 @@ where return Err(tunnel_eof()); } } else { - let n = futures::try_ready!(self.conn.as_mut().unwrap().read_buf(&mut self.buf.get_mut())); + let n = futures::try_ready!(self + .conn + .as_mut() + .unwrap() + .read_buf(&mut self.buf.get_mut())); let read = &self.buf.get_ref()[..]; if n == 0 { return Err(tunnel_eof()); @@ -451,9 +495,12 @@ where if read.ends_with(b"\r\n\r\n") { return Ok(self.conn.take().unwrap().into()); } - // else read more + // else read more } else if read.starts_with(b"HTTP/1.1 407") { - return Err(io::Error::new(io::ErrorKind::Other, "proxy authentication required")); + return Err(io::Error::new( + io::ErrorKind::Other, + "proxy authentication required", + )); } else if read.starts_with(b"HTTP/1.1 403") { return Err(io::Error::new( io::ErrorKind::Other, @@ -477,7 +524,7 @@ where fn tunnel_eof() -> io::Error { io::Error::new( io::ErrorKind::UnexpectedEof, - "unexpected eof while tunneling" + "unexpected eof while tunneling", ) } @@ -485,9 +532,9 @@ fn tunnel_eof() -> io::Error { mod native_tls_async { use std::io::{self, Read, Write}; - use futures::{Poll, Future, Async}; - use native_tls::{self, HandshakeError, Error, TlsConnector}; - use tokio_io::{AsyncRead, AsyncWrite, try_nb}; + use futures::{Async, Future, Poll}; + use native_tls::{self, Error, HandshakeError, TlsConnector}; + use tokio_io::{try_nb, AsyncRead, AsyncWrite}; /// A wrapper around an underlying raw stream which implements the TLS or SSL /// protocol. @@ -533,7 +580,8 @@ mod native_tls_async { /// and `AsyncWrite` traits as well, otherwise this function will not work /// properly. fn connect_async(&self, domain: &str, stream: S) -> ConnectAsync - where S: Read + Write; // TODO: change to AsyncRead + AsyncWrite + where + S: Read + Write; // TODO: change to AsyncRead + AsyncWrite } mod sealed { @@ -556,9 +604,7 @@ mod native_tls_async { } } - - impl AsyncRead for TlsStream { - } + impl AsyncRead for TlsStream {} impl AsyncWrite for TlsStream { fn shutdown(&mut self) -> Poll<(), io::Error> { @@ -569,7 +615,8 @@ mod native_tls_async { impl TlsConnectorExt for TlsConnector { fn connect_async(&self, domain: &str, stream: S) -> ConnectAsync - where S: Read + Write, + where + S: Read + Write, { ConnectAsync { inner: MidHandshake { @@ -600,51 +647,42 @@ mod native_tls_async { match self.inner.take().expect("cannot poll MidHandshake twice") { Ok(stream) => Ok(TlsStream { inner: stream }.into()), Err(HandshakeError::Failure(e)) => Err(e), - Err(HandshakeError::WouldBlock(s)) => { - match s.handshake() { - Ok(stream) => Ok(TlsStream { inner: stream }.into()), - Err(HandshakeError::Failure(e)) => Err(e), - Err(HandshakeError::WouldBlock(s)) => { - self.inner = Some(Err(HandshakeError::WouldBlock(s))); - Ok(Async::NotReady) - } + Err(HandshakeError::WouldBlock(s)) => match s.handshake() { + Ok(stream) => Ok(TlsStream { inner: stream }.into()), + Err(HandshakeError::Failure(e)) => Err(e), + Err(HandshakeError::WouldBlock(s)) => { + self.inner = Some(Err(HandshakeError::WouldBlock(s))); + Ok(Async::NotReady) } - } + }, } } } } - #[cfg(feature = "socks")] mod socks { use std::io; - use futures::{Future, future}; + use futures::{future, Future}; use hyper::client::connect::{Connected, Destination}; use socks::Socks5Stream; use std::net::ToSocketAddrs; use tokio::{net::TcpStream, reactor}; - use super::{Connecting}; - use crate::proxy::{ProxyScheme}; + use super::Connecting; + use crate::proxy::ProxyScheme; pub(super) enum DnsResolve { Local, Proxy, } - pub(super) fn connect( - proxy: ProxyScheme, - dst: Destination, - dns: DnsResolve, - ) -> Connecting { + pub(super) fn connect(proxy: ProxyScheme, dst: Destination, dns: DnsResolve) -> Connecting { let https = dst.scheme() == "https"; let original_host = dst.host().to_owned(); let mut host = original_host.clone(); - let port = dst.port().unwrap_or_else(|| { - if https { 443 } else { 80 } - }); + let port = dst.port().unwrap_or_else(|| if https { 443 } else { 80 }); if let DnsResolve::Local = dns { let maybe_new_target = match (host.as_str(), port).to_socket_addrs() { @@ -664,20 +702,24 @@ mod socks { }; // Get a Tokio TcpStream - let stream = future::result(if let Some((username, password)) = auth { - Socks5Stream::connect_with_password( - socket_addr, (host.as_str(), port), &username, &password - ) - } else { - Socks5Stream::connect(socket_addr, (host.as_str(), port)) - }.and_then(|s| { - TcpStream::from_std(s.into_inner(), &reactor::Handle::default()) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e)) - })); + let stream = future::result( + if let Some((username, password)) = auth { + Socks5Stream::connect_with_password( + socket_addr, + (host.as_str(), port), + &username, + &password, + ) + } else { + Socks5Stream::connect(socket_addr, (host.as_str(), port)) + } + .and_then(|s| { + TcpStream::from_std(s.into_inner(), &reactor::Handle::default()) + .map_err(|e| io::Error::new(io::ErrorKind::Other, e)) + }), + ); - Box::new( - stream.map(|s| (Box::new(s) as super::Conn, Connected::new())) - ) + Box::new(stream.map(|s| (Box::new(s) as super::Conn, Connected::new()))) } } @@ -686,14 +728,14 @@ mod socks { mod tests { extern crate tokio_tcp; - use std::io::{Read, Write}; - use std::net::TcpListener; - use std::thread; - use futures::Future; - use tokio::runtime::current_thread::Runtime; use self::tokio_tcp::TcpStream; use super::tunnel; use crate::proxy; + use futures::Future; + use std::io::{Read, Write}; + use std::net::TcpListener; + use std::thread; + use tokio::runtime::current_thread::Runtime; static TUNNEL_OK: &[u8] = b"\ HTTP/1.1 200 OK\r\n\ @@ -701,21 +743,27 @@ mod tests { "; macro_rules! mock_tunnel { - () => ({ + () => {{ mock_tunnel!(TUNNEL_OK) - }); - ($write:expr) => ({ + }}; + ($write:expr) => {{ mock_tunnel!($write, "") - }); - ($write:expr, $auth:expr) => ({ + }}; + ($write:expr, $auth:expr) => {{ let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let addr = listener.local_addr().unwrap(); - let connect_expected = format!("\ - CONNECT {0}:{1} HTTP/1.1\r\n\ - Host: {0}:{1}\r\n\ - {2}\ - \r\n\ - ", addr.ip(), addr.port(), $auth).into_bytes(); + let connect_expected = format!( + "\ + CONNECT {0}:{1} HTTP/1.1\r\n\ + Host: {0}:{1}\r\n\ + {2}\ + \r\n\ + ", + addr.ip(), + addr.port(), + $auth + ) + .into_bytes(); thread::spawn(move || { let (mut sock, _) = listener.accept().unwrap(); @@ -726,7 +774,7 @@ mod tests { sock.write_all($write).unwrap(); }); addr - }) + }}; } #[test] @@ -737,9 +785,7 @@ mod tests { let work = TcpStream::connect(&addr); let host = addr.ip().to_string(); let port = addr.port(); - let work = work.and_then(|tcp| { - tunnel(tcp, host, port, None) - }); + let work = work.and_then(|tcp| tunnel(tcp, host, port, None)); rt.block_on(work).unwrap(); } @@ -752,9 +798,7 @@ mod tests { let work = TcpStream::connect(&addr); let host = addr.ip().to_string(); let port = addr.port(); - let work = work.and_then(|tcp| { - tunnel(tcp, host, port, None) - }); + let work = work.and_then(|tcp| tunnel(tcp, host, port, None)); rt.block_on(work).unwrap_err(); } @@ -767,28 +811,26 @@ mod tests { let work = TcpStream::connect(&addr); let host = addr.ip().to_string(); let port = addr.port(); - let work = work.and_then(|tcp| { - tunnel(tcp, host, port, None) - }); + let work = work.and_then(|tcp| tunnel(tcp, host, port, None)); rt.block_on(work).unwrap_err(); } #[test] fn test_tunnel_proxy_unauthorized() { - let addr = mock_tunnel!(b"\ + let addr = mock_tunnel!( + b"\ HTTP/1.1 407 Proxy Authentication Required\r\n\ Proxy-Authenticate: Basic realm=\"nope\"\r\n\ \r\n\ - "); + " + ); let mut rt = Runtime::new().unwrap(); let work = TcpStream::connect(&addr); let host = addr.ip().to_string(); let port = addr.port(); - let work = work.and_then(|tcp| { - tunnel(tcp, host, port, None) - }); + let work = work.and_then(|tcp| tunnel(tcp, host, port, None)); let error = rt.block_on(work).unwrap_err(); assert_eq!(error.to_string(), "proxy authentication required"); @@ -806,7 +848,12 @@ mod tests { let host = addr.ip().to_string(); let port = addr.port(); let work = work.and_then(|tcp| { - tunnel(tcp, host, port, Some(proxy::encode_basic_auth("Aladdin", "open sesame"))) + tunnel( + tcp, + host, + port, + Some(proxy::encode_basic_auth("Aladdin", "open sesame")), + ) }); rt.block_on(work).unwrap(); diff --git a/src/cookie.rs b/src/cookie.rs index f3f1382..f217884 100644 --- a/src/cookie.rs +++ b/src/cookie.rs @@ -109,7 +109,9 @@ impl<'a> Cookie<'a> { /// Get the Max-Age information. pub fn max_age(&self) -> Option { - self.0.max_age().map(|d| std::time::Duration::new(d.num_seconds() as u64, 0)) + self.0 + .max_age() + .map(|d| std::time::Duration::new(d.num_seconds() as u64, 0)) } /// The cookie expiration time. diff --git a/src/dns.rs b/src/dns.rs index 06b1aae..726d9e9 100644 --- a/src/dns.rs +++ b/src/dns.rs @@ -1,6 +1,6 @@ -use std::{io, vec}; use std::net::IpAddr; use std::sync::{Arc, Mutex, Once}; +use std::{io, vec}; use futures::{future, Future}; use hyper::client::connect::dns as hyper_dns; @@ -13,7 +13,7 @@ use trust_dns_resolver::{system_conf, AsyncResolver, BackgroundLookupIp}; // // "Erasing" the internal resolver type saves us from this limit. type ErasedResolver = Box BackgroundLookupIp + Send + Sync>; -type Background = Box + Send>; +type Background = Box + Send>; #[derive(Clone)] pub(crate) struct TrustDnsResolver { @@ -31,9 +31,7 @@ impl TrustDnsResolver { let (conf, opts) = system_conf::read_system_conf()?; let (resolver, bg) = AsyncResolver::new(conf, opts); - let resolver: ErasedResolver = Box::new(move |name| { - resolver.lookup_ip(name.as_str()) - }); + let resolver: ErasedResolver = Box::new(move |name| resolver.lookup_ip(name.as_str())); let background = Mutex::new(Some(Box::new(bg) as Background)); let once = Once::new(); @@ -49,7 +47,7 @@ impl TrustDnsResolver { impl hyper_dns::Resolve for TrustDnsResolver { type Addrs = vec::IntoIter; - type Future = Box + Send>; + type Future = Box + Send>; fn resolve(&self, name: hyper_dns::Name) -> Self::Future { let inner = self.inner.clone(); @@ -70,16 +68,8 @@ impl hyper_dns::Resolve for TrustDnsResolver { }); (inner.resolver)(name) - .map(|lookup| { - lookup - .iter() - .collect::>() - .into_iter() - }) - .map_err(|err| { - io::Error::new(io::ErrorKind::Other, err.to_string()) - }) + .map(|lookup| lookup.iter().collect::>().into_iter()) + .map_err(|err| io::Error::new(io::ErrorKind::Other, err.to_string())) })) } } - diff --git a/src/error.rs b/src/error.rs index 47127a7..694ebe9 100644 --- a/src/error.rs +++ b/src/error.rs @@ -62,17 +62,13 @@ struct Inner { url: Option, } - /// A `Result` alias where the `Err` case is `reqwest::Error`. pub type Result = std::result::Result; impl Error { fn new(kind: Kind, url: Option) -> Error { Error { - inner: Box::new(Inner { - kind, - url, - }), + inner: Box::new(Inner { kind, url }), } } @@ -148,13 +144,13 @@ impl Error { Kind::Io(ref e) => Some(e), Kind::UrlEncoded(ref e) => Some(e), Kind::Json(ref e) => Some(e), - Kind::UrlBadScheme | - Kind::TooManyRedirects | - Kind::RedirectLoop | - Kind::Status(_) | - Kind::UnknownProxyScheme | - Kind::Timer | - Kind::BlockingClientInFutureContext => None, + Kind::UrlBadScheme + | Kind::TooManyRedirects + | Kind::RedirectLoop + | Kind::Status(_) + | Kind::UnknownProxyScheme + | Kind::Timer + | Kind::BlockingClientInFutureContext => None, } } @@ -172,15 +168,11 @@ impl Error { pub fn is_timeout(&self) -> bool { match self.inner.kind { Kind::Io(ref io) => io.kind() == io::ErrorKind::TimedOut, - Kind::Hyper(ref error) => { - error - .source() - .and_then(|cause| { - cause.downcast_ref::() - }) - .map(|io| io.kind() == io::ErrorKind::TimedOut) - .unwrap_or(false) - }, + Kind::Hyper(ref error) => error + .source() + .and_then(|cause| cause.downcast_ref::()) + .map(|io| io.kind() == io::ErrorKind::TimedOut) + .unwrap_or(false), _ => false, } } @@ -189,8 +181,7 @@ impl Error { #[inline] pub fn is_serialization(&self) -> bool { match self.inner.kind { - Kind::Json(_) | - Kind::UrlEncoded(_) => true, + Kind::Json(_) | Kind::UrlEncoded(_) => true, _ => false, } } @@ -199,8 +190,7 @@ impl Error { #[inline] pub fn is_redirect(&self) -> bool { match self.inner.kind { - Kind::TooManyRedirects | - Kind::RedirectLoop => true, + Kind::TooManyRedirects | Kind::RedirectLoop => true, _ => false, } } @@ -241,9 +231,7 @@ impl fmt::Debug for Error { .field(url) .finish() } else { - f.debug_tuple("Error") - .field(&self.inner.kind) - .finish() + f.debug_tuple("Error").field(&self.inner.kind).finish() } } } @@ -269,9 +257,7 @@ impl fmt::Display for Error { #[cfg(feature = "rustls-tls")] Kind::Rustls(ref e) => fmt::Display::fmt(e, f), #[cfg(feature = "trust-dns")] - Kind::DnsSystemConf(ref e) => { - write!(f, "failed to load DNS system conf: {}", e) - }, + Kind::DnsSystemConf(ref e) => write!(f, "failed to load DNS system conf: {}", e), Kind::Io(ref e) => fmt::Display::fmt(e, f), Kind::UrlEncoded(ref e) => fmt::Display::fmt(e, f), Kind::Json(ref e) => fmt::Display::fmt(e, f), @@ -349,13 +335,13 @@ impl StdError for Error { Kind::Io(ref e) => e.cause(), Kind::UrlEncoded(ref e) => e.cause(), Kind::Json(ref e) => e.cause(), - Kind::UrlBadScheme | - Kind::TooManyRedirects | - Kind::RedirectLoop | - Kind::Status(_) | - Kind::UnknownProxyScheme | - Kind::Timer | - Kind::BlockingClientInFutureContext => None, + Kind::UrlBadScheme + | Kind::TooManyRedirects + | Kind::RedirectLoop + | Kind::Status(_) + | Kind::UnknownProxyScheme + | Kind::Timer + | Kind::BlockingClientInFutureContext => None, } } @@ -376,13 +362,13 @@ impl StdError for Error { Kind::Io(ref e) => e.source(), Kind::UrlEncoded(ref e) => e.source(), Kind::Json(ref e) => e.source(), - Kind::UrlBadScheme | - Kind::TooManyRedirects | - Kind::RedirectLoop | - Kind::Status(_) | - Kind::UnknownProxyScheme | - Kind::Timer | - Kind::BlockingClientInFutureContext => None, + Kind::UrlBadScheme + | Kind::TooManyRedirects + | Kind::RedirectLoop + | Kind::Status(_) + | Kind::UnknownProxyScheme + | Kind::Timer + | Kind::BlockingClientInFutureContext => None, } } } @@ -413,7 +399,6 @@ pub(crate) enum Kind { BlockingClientInFutureContext, } - impl From for Kind { #[inline] fn from(err: http::Error) -> Kind { @@ -478,10 +463,12 @@ impl From for Kind { } impl From> for Kind -where T: Into { +where + T: Into, +{ fn from(err: crate::wait::Waited) -> Kind { match err { - crate::wait::Waited::TimedOut => io_timeout().into(), + crate::wait::Waited::TimedOut => io_timeout().into(), crate::wait::Waited::Executor(e) => e.into(), crate::wait::Waited::Inner(e) => e.into(), } @@ -542,8 +529,7 @@ pub(crate) fn into_io(e: Error) -> io::Error { pub(crate) fn from_io(e: io::Error) -> Error { if e.get_ref().map(|r| r.is::()).unwrap_or(false) { - *e - .into_inner() + *e.into_inner() .expect("io::Error::get_ref was Some(_)") .downcast::() .expect("StdError::is() was true") @@ -552,28 +538,30 @@ pub(crate) fn from_io(e: io::Error) -> Error { } } - macro_rules! try_ { - ($e:expr) => ( + ($e:expr) => { match $e { Ok(v) => v, Err(err) => { return Err(crate::error::from(err)); } } - ); - ($e:expr, $url:expr) => ( + }; + ($e:expr, $url:expr) => { match $e { Ok(v) => v, Err(err) => { - return Err(crate::Error::from(crate::error::InternalFrom(err, Some($url.clone())))); + return Err(crate::Error::from(crate::error::InternalFrom( + err, + Some($url.clone()), + ))); } } - ) + }; } macro_rules! try_io { - ($e:expr) => ( + ($e:expr) => { match $e { Ok(v) => v, Err(ref err) if err.kind() == std::io::ErrorKind::WouldBlock => { @@ -583,7 +571,7 @@ macro_rules! try_io { return Err(crate::error::from_io(err)); } } - ) + }; } pub(crate) fn loop_detected(url: Url) -> Error { @@ -625,7 +613,7 @@ mod tests { #[derive(Debug)] struct Chain(Option); - impl fmt::Display for Chain { + impl fmt::Display for Chain { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if let Some(ref link) = self.0 { write!(f, "chain: {}", link) @@ -658,7 +646,6 @@ mod tests { assert!(err.cause().is_none()); assert_eq!(err.to_string(), "root"); - let root = std::io::Error::new(std::io::ErrorKind::Other, Chain(None::)); let link = Chain(Some(root)); let io = std::io::Error::new(std::io::ErrorKind::Other, link); diff --git a/src/into_url.rs b/src/into_url.rs index b5c7149..3442d5c 100644 --- a/src/into_url.rs +++ b/src/into_url.rs @@ -27,8 +27,7 @@ impl PolyfillTryInto for Url { impl<'a> PolyfillTryInto for &'a str { fn into_url(self) -> crate::Result { - try_!(Url::parse(self)) - .into_url() + try_!(Url::parse(self)).into_url() } } @@ -39,7 +38,9 @@ impl<'a> PolyfillTryInto for &'a String { } pub(crate) fn expect_uri(url: &Url) -> hyper::Uri { - url.as_str().parse().expect("a parsed Url should always be a valid Uri") + url.as_str() + .parse() + .expect("a parsed Url should always be a valid Uri") } pub(crate) fn try_uri(url: &Url) -> Option { @@ -52,9 +53,10 @@ mod tests { #[test] fn into_url_file_scheme() { - let err = "file:///etc/hosts" - .into_url() - .unwrap_err(); - assert_eq!(err.to_string(), "file:///etc/hosts: URL scheme is not allowed"); + let err = "file:///etc/hosts".into_url().unwrap_err(); + assert_eq!( + err.to_string(), + "file:///etc/hosts: URL scheme is not allowed" + ); } } diff --git a/src/lib.rs b/src/lib.rs index 083b464..9c007be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -187,12 +187,12 @@ doctest!("../README.md"); pub use hyper::header; pub use hyper::Method; pub use hyper::{StatusCode, Version}; -pub use url::Url; pub use url::ParseError as UrlError; +pub use url::Url; +pub use self::body::Body; pub use self::client::{Client, ClientBuilder}; pub use self::error::{Error, Result}; -pub use self::body::Body; pub use self::into_url::IntoUrl; pub use self::proxy::Proxy; pub use self::redirect::{RedirectAction, RedirectAttempt, RedirectPolicy}; @@ -206,9 +206,9 @@ pub use self::tls::{Certificate, Identity}; mod error; mod async_impl; -mod connect; mod body; mod client; +mod connect; pub mod cookie; #[cfg(feature = "trust-dns")] mod dns; @@ -226,16 +226,8 @@ pub mod multipart; /// An 'async' implementation of the reqwest `Client`. pub mod r#async { pub use crate::async_impl::{ - Body, - Chunk, - Decoder, - Client, - ClientBuilder, - Request, - RequestBuilder, - Response, + multipart, Body, Chunk, Client, ClientBuilder, Decoder, Request, RequestBuilder, Response, ResponseBuilderExt, - multipart }; } @@ -269,10 +261,7 @@ pub mod r#async { /// - redirect loop was detected /// - redirect limit was exhausted pub fn get(url: T) -> crate::Result { - Client::builder() - .build()? - .get(url) - .send() + Client::builder().build()?.get(url).send() } fn _assert_impls() { diff --git a/src/multipart.rs b/src/multipart.rs index 6090b6a..0ace3bb 100644 --- a/src/multipart.rs +++ b/src/multipart.rs @@ -45,7 +45,7 @@ use std::path::Path; use mime_guess::{self, Mime}; use crate::async_impl::multipart::{FormParts, PartMetadata, PartProps}; -use crate::{Body}; +use crate::Body; /// A multipart/form-data request. pub struct Form { @@ -82,8 +82,9 @@ impl Form { /// .text("password", "secret"); /// ``` pub fn text(self, name: T, value: U) -> Form - where T: Into>, - U: Into>, + where + T: Into>, + U: Into>, { self.part(name, Part::text(value)) } @@ -106,8 +107,9 @@ impl Form { /// /// Errors when the file cannot be opened. pub fn file(self, name: T, path: U) -> io::Result

- where T: Into>, - U: AsRef + where + T: Into>, + U: AsRef, { Ok(self.part(name, Part::file(path)?)) } @@ -162,11 +164,11 @@ impl fmt::Debug for Form { } } - impl Part { /// Makes a text parameter. pub fn text(value: T) -> Part - where T: Into>, + where + T: Into>, { let body = match value.into() { Cow::Borrowed(slice) => Body::from(slice), @@ -177,7 +179,8 @@ impl Part { /// Makes a new parameter from arbitrary bytes. pub fn bytes(value: T) -> Part - where T: Into> + where + T: Into>, { let body = match value.into() { Cow::Borrowed(slice) => Body::from(slice), @@ -207,16 +210,14 @@ impl Part { /// Errors when the file cannot be opened. pub fn file>(path: T) -> io::Result { let path = path.as_ref(); - let file_name = path.file_name().and_then(|filename| { - Some(filename.to_string_lossy().into_owned()) - }); - let ext = path.extension() - .and_then(|ext| ext.to_str()) - .unwrap_or(""); + let file_name = path + .file_name() + .map(|filename| filename.to_string_lossy().into_owned()); + + let ext = path.extension().and_then(|ext| ext.to_str()).unwrap_or(""); let mime = mime_guess::from_ext(ext).first_or_octet_stream(); let file = File::open(path)?; - let field = Part::new(Body::from(file)) - .mime(mime); + let field = Part::new(Body::from(file)).mime(mime); Ok(if let Some(file_name) = file_name { field.file_name(file_name) @@ -287,9 +288,7 @@ pub(crate) struct Reader { impl fmt::Debug for Reader { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Reader") - .field("form", &self.form) - .finish() + f.debug_struct("Reader").field("form", &self.form).finish() } } @@ -313,7 +312,10 @@ impl Reader { let mut h = if !self.form.inner.computed_headers.is_empty() { self.form.inner.computed_headers.remove(0) } else { - self.form.inner.percent_encoding.encode_headers(&name, field.metadata()) + self.form + .inner + .percent_encoding + .encode_headers(&name, field.metadata()) }; h.extend_from_slice(b"\r\n\r\n"); h @@ -327,9 +329,10 @@ impl Reader { if !self.form.inner.fields.is_empty() { Some(Box::new(reader)) } else { - Some(Box::new(reader.chain(Cursor::new( - format!("--{}--\r\n", self.form.boundary()), - )))) + Some(Box::new(reader.chain(Cursor::new(format!( + "--{}--\r\n", + self.form.boundary() + ))))) } } else { None @@ -379,33 +382,28 @@ mod tests { let mut form = Form::new() .part("reader1", Part::reader(std::io::empty())) .part("key1", Part::text("value1")) - .part( - "key2", - Part::text("value2").mime(mime::IMAGE_BMP), - ) + .part("key2", Part::text("value2").mime(mime::IMAGE_BMP)) .part("reader2", Part::reader(std::io::empty())) - .part( - "key3", - Part::text("value3").file_name("filename"), - ); + .part("key3", Part::text("value3").file_name("filename")); form.inner.boundary = "boundary".to_string(); let length = form.compute_length(); - let expected = "--boundary\r\n\ - Content-Disposition: form-data; name=\"reader1\"\r\n\r\n\ - \r\n\ - --boundary\r\n\ - Content-Disposition: form-data; name=\"key1\"\r\n\r\n\ - value1\r\n\ - --boundary\r\n\ - Content-Disposition: form-data; name=\"key2\"\r\n\ - Content-Type: image/bmp\r\n\r\n\ - value2\r\n\ - --boundary\r\n\ - Content-Disposition: form-data; name=\"reader2\"\r\n\r\n\ - \r\n\ - --boundary\r\n\ - Content-Disposition: form-data; name=\"key3\"; filename=\"filename\"\r\n\r\n\ - value3\r\n--boundary--\r\n"; + let expected = + "--boundary\r\n\ + Content-Disposition: form-data; name=\"reader1\"\r\n\r\n\ + \r\n\ + --boundary\r\n\ + Content-Disposition: form-data; name=\"key1\"\r\n\r\n\ + value1\r\n\ + --boundary\r\n\ + Content-Disposition: form-data; name=\"key2\"\r\n\ + Content-Type: image/bmp\r\n\r\n\ + value2\r\n\ + --boundary\r\n\ + Content-Disposition: form-data; name=\"reader2\"\r\n\r\n\ + \r\n\ + --boundary\r\n\ + Content-Disposition: form-data; name=\"key3\"; filename=\"filename\"\r\n\r\n\ + value3\r\n--boundary--\r\n"; form.reader().read_to_end(&mut output).unwrap(); // These prints are for debug purposes in case the test fails println!( @@ -422,26 +420,21 @@ mod tests { let mut output = Vec::new(); let mut form = Form::new() .text("key1", "value1") - .part( - "key2", - Part::text("value2").mime(mime::IMAGE_BMP), - ) - .part( - "key3", - Part::text("value3").file_name("filename"), - ); + .part("key2", Part::text("value2").mime(mime::IMAGE_BMP)) + .part("key3", Part::text("value3").file_name("filename")); form.inner.boundary = "boundary".to_string(); let length = form.compute_length(); - let expected = "--boundary\r\n\ - Content-Disposition: form-data; name=\"key1\"\r\n\r\n\ - value1\r\n\ - --boundary\r\n\ - Content-Disposition: form-data; name=\"key2\"\r\n\ - Content-Type: image/bmp\r\n\r\n\ - value2\r\n\ - --boundary\r\n\ - Content-Disposition: form-data; name=\"key3\"; filename=\"filename\"\r\n\r\n\ - value3\r\n--boundary--\r\n"; + let expected = + "--boundary\r\n\ + Content-Disposition: form-data; name=\"key1\"\r\n\r\n\ + value1\r\n\ + --boundary\r\n\ + Content-Disposition: form-data; name=\"key2\"\r\n\ + Content-Type: image/bmp\r\n\r\n\ + value2\r\n\ + --boundary\r\n\ + Content-Disposition: form-data; name=\"key3\"; filename=\"filename\"\r\n\r\n\ + value3\r\n--boundary--\r\n"; form.reader().read_to_end(&mut output).unwrap(); // These prints are for debug purposes in case the test fails println!( diff --git a/src/proxy.rs b/src/proxy.rs index 907f70d..d2457a6 100644 --- a/src/proxy.rs +++ b/src/proxy.rs @@ -1,16 +1,16 @@ use std::fmt; -use std::sync::Arc; #[cfg(feature = "socks")] use std::net::{SocketAddr, ToSocketAddrs}; +use std::sync::Arc; +use crate::{IntoUrl, Url}; use http::{header::HeaderValue, Uri}; use hyper::client::connect::Destination; -use url::percent_encoding::percent_decode; -use crate::{IntoUrl, Url}; use std::collections::HashMap; use std::env; #[cfg(target_os = "windows")] use std::error::Error; +use url::percent_encoding::percent_decode; #[cfg(target_os = "windows")] use winreg::enums::HKEY_CURRENT_USER; #[cfg(target_os = "windows")] @@ -98,7 +98,7 @@ impl Proxy { /// ``` pub fn http(proxy_scheme: U) -> crate::Result { Ok(Proxy::new(Intercept::Http( - proxy_scheme.into_proxy_scheme()? + proxy_scheme.into_proxy_scheme()?, ))) } @@ -118,7 +118,7 @@ impl Proxy { /// ``` pub fn https(proxy_scheme: U) -> crate::Result { Ok(Proxy::new(Intercept::Https( - proxy_scheme.into_proxy_scheme()? + proxy_scheme.into_proxy_scheme()?, ))) } @@ -138,7 +138,7 @@ impl Proxy { /// ``` pub fn all(proxy_scheme: U) -> crate::Result { Ok(Proxy::new(Intercept::All( - proxy_scheme.into_proxy_scheme()? + proxy_scheme.into_proxy_scheme()?, ))) } @@ -163,12 +163,12 @@ impl Proxy { /// # } /// # fn main() {} pub fn custom(fun: F) -> Proxy - where F: Fn(&Url) -> Option + Send + Sync + 'static { + where + F: Fn(&Url) -> Option + Send + Sync + 'static, + { Proxy::new(Intercept::Custom(Custom { auth: None, - func: Arc::new(move |url| { - fun(url).map(IntoProxyScheme::into_proxy_scheme) - }), + func: Arc::new(move |url| fun(url).map(IntoProxyScheme::into_proxy_scheme)), })) } @@ -179,9 +179,7 @@ impl Proxy { */ fn new(intercept: Intercept) -> Proxy { - Proxy { - intercept, - } + Proxy { intercept } } /// Set the `Proxy-Authorization` header using Basic auth. @@ -214,15 +212,13 @@ impl Proxy { pub(crate) fn http_basic_auth(&self, uri: &D) -> Option { match self.intercept { - Intercept::All(ProxyScheme::Http { ref auth, .. }) | - Intercept::Http(ProxyScheme::Http { ref auth, .. }) => auth.clone(), - Intercept::Custom(ref custom) => { - custom.call(uri).and_then(|scheme| match scheme { - ProxyScheme::Http { auth, .. } => auth, - #[cfg(feature = "socks")] - _ => None, - }) - } + Intercept::All(ProxyScheme::Http { ref auth, .. }) + | Intercept::Http(ProxyScheme::Http { ref auth, .. }) => auth.clone(), + Intercept::Custom(ref custom) => custom.call(uri).and_then(|scheme| match scheme { + ProxyScheme::Http { auth, .. } => auth, + #[cfg(feature = "socks")] + _ => None, + }), _ => None, } } @@ -236,14 +232,14 @@ impl Proxy { } else { None } - }, + } Intercept::Https(ref u) => { if uri.scheme() == "https" { Some(u.clone()) } else { None } - }, + } Intercept::Custom(ref custom) => custom.call(uri), } } @@ -251,12 +247,8 @@ impl Proxy { pub(crate) fn is_match(&self, uri: &D) -> bool { match self.intercept { Intercept::All(_) => true, - Intercept::Http(_) => { - uri.scheme() == "http" - }, - Intercept::Https(_) => { - uri.scheme() == "https" - }, + Intercept::Http(_) => uri.scheme() == "http", + Intercept::Https(_) => uri.scheme() == "https", Intercept::Custom(ref custom) => custom.call(uri).is_some(), } } @@ -304,7 +296,11 @@ impl ProxyScheme { } /// Use a username and password when connecting to the proxy server - fn with_basic_auth, U: Into>(mut self, username: T, password: U) -> Self { + fn with_basic_auth, U: Into>( + mut self, + username: T, + password: U, + ) -> Self { self.set_basic_auth(username, password); self } @@ -314,7 +310,7 @@ impl ProxyScheme { ProxyScheme::Http { ref mut auth, .. } => { let header = encode_basic_auth(&username.into(), &password.into()); *auth = Some(header); - }, + } #[cfg(feature = "socks")] ProxyScheme::Socks5 { ref mut auth, .. } => { *auth = Some((username.into(), password.into())); @@ -332,12 +328,10 @@ impl ProxyScheme { let to_addr = || { let host_and_port = try_!(url.with_default_port(|url| match url.scheme() { "socks5" | "socks5h" => Ok(1080), - _ => Err(()) + _ => Err(()), })); let mut addr = try_!(host_and_port.to_socket_addrs()); - addr - .next() - .ok_or_else(crate::error::unknown_proxy_scheme) + addr.next().ok_or_else(crate::error::unknown_proxy_scheme) }; let mut scheme = match url.scheme() { @@ -346,7 +340,7 @@ impl ProxyScheme { "socks5" => Self::socks5(to_addr()?)?, #[cfg(feature = "socks")] "socks5h" => Self::socks5h(to_addr()?)?, - _ => return Err(crate::error::unknown_proxy_scheme()) + _ => return Err(crate::error::unknown_proxy_scheme()), }; if let Some(pwd) = url.password() { @@ -359,8 +353,6 @@ impl ProxyScheme { } } - - #[derive(Clone, Debug)] enum Intercept { All(ProxyScheme), @@ -372,9 +364,9 @@ enum Intercept { impl Intercept { fn set_basic_auth(&mut self, username: &str, password: &str) { match self { - Intercept::All(ref mut s) | - Intercept::Http(ref mut s) | - Intercept::Https(ref mut s) => s.set_basic_auth(username, password), + Intercept::All(ref mut s) + | Intercept::Http(ref mut s) + | Intercept::Https(ref mut s) => s.set_basic_auth(username, password), Intercept::Custom(ref mut custom) => { let header = encode_basic_auth(username, password); custom.auth = Some(header); @@ -397,9 +389,10 @@ impl Custom { uri.scheme(), uri.host(), uri.port().map(|_| ":").unwrap_or(""), - uri.port().map(|p| p.to_string()).unwrap_or_default()) - .parse() - .expect("should be valid Url"); + uri.port().map(|p| p.to_string()).unwrap_or_default() + ) + .parse() + .expect("should be valid Url"); (self.func)(&url) .and_then(|result| result.ok()) @@ -413,7 +406,7 @@ impl Custom { uri, } } - }, + } #[cfg(feature = "socks")] socks => socks, }) @@ -467,8 +460,7 @@ impl Dst for Uri { } fn host(&self) -> &str { - Uri::host(self) - .expect("::host should have a str") + Uri::host(self).expect("::host should have a str") } fn port(&self) -> Option { @@ -499,8 +491,7 @@ pub fn get_proxies() -> HashMap { proxies } -fn insert_proxy(proxies: &mut HashMap, schema: String, addr: String) -{ +fn insert_proxy(proxies: &mut HashMap, schema: String, addr: String) { if let Ok(valid_addr) = Url::parse(&addr) { proxies.insert(schema, valid_addr); } @@ -522,7 +513,6 @@ fn get_from_environment() -> HashMap { proxies } - #[cfg(target_os = "windows")] fn get_from_registry_impl() -> Result, Box> { let hkcu = RegKey::predef(HKEY_CURRENT_USER); @@ -543,7 +533,11 @@ fn get_from_registry_impl() -> Result, Box> { let protocol_parts: Vec<&str> = p.split("=").collect(); match protocol_parts.as_slice() { [protocol, address] => { - insert_proxy(&mut proxies, String::from(*protocol), String::from(*address)); + insert_proxy( + &mut proxies, + String::from(*protocol), + String::from(*address), + ); } _ => { // Contains invalid protocol setting, just break the loop @@ -558,9 +552,21 @@ fn get_from_registry_impl() -> Result, Box> { if proxy_server.starts_with("http:") { insert_proxy(&mut proxies, String::from("http"), proxy_server); } else { - insert_proxy(&mut proxies, String::from("http"), format!("http://{}", proxy_server)); - insert_proxy(&mut proxies, String::from("https"), format!("https://{}", proxy_server)); - insert_proxy(&mut proxies, String::from("ftp"), format!("https://{}", proxy_server)); + insert_proxy( + &mut proxies, + String::from("http"), + format!("http://{}", proxy_server), + ); + insert_proxy( + &mut proxies, + String::from("https"), + format!("https://{}", proxy_server), + ); + insert_proxy( + &mut proxies, + String::from("ftp"), + format!("https://{}", proxy_server), + ); } } Ok(proxies) @@ -581,8 +587,7 @@ mod tests { } fn host(&self) -> &str { - Url::host_str(self) - .expect("::host should have a str") + Url::host_str(self).expect("::host should have a str") } fn port(&self) -> Option { @@ -594,7 +599,6 @@ mod tests { s.parse().unwrap() } - fn intercepted_uri(p: &Proxy, s: &str) -> Uri { match p.intercept(&url(s)).unwrap() { ProxyScheme::Http { uri, .. } => uri, @@ -641,7 +645,6 @@ mod tests { assert_eq!(intercepted_uri(&p, other), target); } - #[test] fn test_custom() { let target1 = "http://example.domain/"; @@ -687,7 +690,7 @@ mod tests { // reset user setting. match system_proxy { Err(_) => env::remove_var("http_proxy"), - Ok(proxy) => env::set_var("http_proxy", proxy) + Ok(proxy) => env::set_var("http_proxy", proxy), } } } diff --git a/src/redirect.rs b/src/redirect.rs index 600d7b1..99b6e2f 100644 --- a/src/redirect.rs +++ b/src/redirect.rs @@ -1,13 +1,6 @@ use std::fmt; -use crate::header::{ - HeaderMap, - AUTHORIZATION, - COOKIE, - PROXY_AUTHORIZATION, - WWW_AUTHENTICATE, - -}; +use crate::header::{HeaderMap, AUTHORIZATION, COOKIE, PROXY_AUTHORIZATION, WWW_AUTHENTICATE}; use hyper::StatusCode; use crate::Url; @@ -141,19 +134,13 @@ impl RedirectPolicy { } } - pub(crate) fn check( - &self, - status: StatusCode, - next: &Url, - previous: &[Url], - ) -> Action { - self - .redirect(RedirectAttempt { - status, - next, - previous, - }) - .inner + pub(crate) fn check(&self, status: StatusCode, next: &Url, previous: &[Url]) -> Action { + self.redirect(RedirectAttempt { + status, + next, + previous, + }) + .inner } } @@ -239,11 +226,10 @@ pub(crate) enum Action { TooManyRedirects, } - pub(crate) fn remove_sensitive_headers(headers: &mut HeaderMap, next: &Url, previous: &[Url]) { if let Some(previous) = previous.last() { - let cross_host = next.host_str() != previous.host_str() || - next.port_or_known_default() != previous.port_or_known_default(); + let cross_host = next.host_str() != previous.host_str() + || next.port_or_known_default() != previous.port_or_known_default(); if cross_host { headers.remove(AUTHORIZATION); headers.remove(COOKIE); @@ -304,21 +290,15 @@ fn test_redirect_policy_custom() { }); let next = Url::parse("http://bar/baz").unwrap(); - assert_eq!( - policy.check(StatusCode::FOUND, &next, &[]), - Action::Follow - ); + assert_eq!(policy.check(StatusCode::FOUND, &next, &[]), Action::Follow); let next = Url::parse("http://foo/baz").unwrap(); - assert_eq!( - policy.check(StatusCode::FOUND, &next, &[]), - Action::Stop - ); + assert_eq!(policy.check(StatusCode::FOUND, &next, &[]), Action::Stop); } #[test] fn test_remove_sensitive_headers() { - use hyper::header::{ACCEPT, AUTHORIZATION, COOKIE, HeaderValue}; + use hyper::header::{HeaderValue, ACCEPT, AUTHORIZATION, COOKIE}; let mut headers = HeaderMap::new(); headers.insert(ACCEPT, HeaderValue::from_static("*/*")); diff --git a/src/request.rs b/src/request.rs index fb6def8..e994b8e 100644 --- a/src/request.rs +++ b/src/request.rs @@ -7,8 +7,8 @@ use serde_urlencoded; use crate::body::{self, Body}; use crate::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_TYPE}; -use http::HttpTryFrom; use crate::{async_impl, Client, Method, Url}; +use http::HttpTryFrom; /// A request which can be executed with `Client::execute()`. pub struct Request { @@ -119,10 +119,7 @@ impl Request { impl RequestBuilder { pub(crate) fn new(client: Client, request: crate::Result) -> RequestBuilder { - RequestBuilder { - client, - request, - } + RequestBuilder { client, request } } /// Add a `Header` to this Request. @@ -146,11 +143,11 @@ impl RequestBuilder { let mut error = None; if let Ok(ref mut req) = self.request { match >::try_from(key) { - Ok(key) => { - match >::try_from(value) { - Ok(value) => { req.headers_mut().append(key, value); } - Err(e) => error = Some(crate::error::from(e.into())), + Ok(key) => match >::try_from(value) { + Ok(value) => { + req.headers_mut().append(key, value); } + Err(e) => error = Some(crate::error::from(e.into())), }, Err(e) => error = Some(crate::error::from(e.into())), }; @@ -236,7 +233,7 @@ impl RequestBuilder { { let auth = match password { Some(password) => format!("{}:{}", username, password), - None => format!("{}:", username) + None => format!("{}:", username), }; let header_value = format!("Basic {}", encode(&auth)); self.header(crate::header::AUTHORIZATION, &*header_value) @@ -397,10 +394,10 @@ impl RequestBuilder { Ok(body) => { req.headers_mut().insert( CONTENT_TYPE, - HeaderValue::from_static("application/x-www-form-urlencoded") + HeaderValue::from_static("application/x-www-form-urlencoded"), ); *req.body_mut() = Some(body.into()); - }, + } Err(err) => error = Some(crate::error::from(err)), } } @@ -440,12 +437,10 @@ impl RequestBuilder { if let Ok(ref mut req) = self.request { match serde_json::to_vec(json) { Ok(body) => { - req.headers_mut().insert( - CONTENT_TYPE, - HeaderValue::from_static("application/json") - ); + req.headers_mut() + .insert(CONTENT_TYPE, HeaderValue::from_static("application/json")); *req.body_mut() = Some(body.into()); - }, + } Err(err) => error = Some(crate::error::from(err)), } } @@ -477,10 +472,7 @@ impl RequestBuilder { pub fn multipart(self, mut multipart: crate::multipart::Form) -> RequestBuilder { let mut builder = self.header( CONTENT_TYPE, - format!( - "multipart/form-data; boundary={}", - multipart.boundary() - ).as_str() + format!("multipart/form-data; boundary={}", multipart.boundary()).as_str(), ); if let Ok(ref mut req) = builder.request { *req.body_mut() = Some(match multipart.compute_length() { @@ -552,26 +544,27 @@ impl RequestBuilder { /// # } /// ``` pub fn try_clone(&self) -> Option { - self.request.as_ref() + self.request + .as_ref() .ok() .and_then(|req| req.try_clone()) - .map(|req| { - RequestBuilder{ - client: self.client.clone(), - request: Ok(req), - } + .map(|req| RequestBuilder { + client: self.client.clone(), + request: Ok(req), }) } } impl fmt::Debug for Request { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt_request_fields(&mut f.debug_struct("Request"), self) - .finish() + fmt_request_fields(&mut f.debug_struct("Request"), self).finish() } } -fn fmt_request_fields<'a, 'b>(f: &'a mut fmt::DebugStruct<'a, 'b>, req: &Request) -> &'a mut fmt::DebugStruct<'a, 'b> { +fn fmt_request_fields<'a, 'b>( + f: &'a mut fmt::DebugStruct<'a, 'b>, + req: &Request, +) -> &'a mut fmt::DebugStruct<'a, 'b> { f.field("method", req.method()) .field("url", req.url()) .field("headers", req.headers()) @@ -579,12 +572,12 @@ fn fmt_request_fields<'a, 'b>(f: &'a mut fmt::DebugStruct<'a, 'b>, req: &Request #[cfg(test)] mod tests { + use crate::header::{HeaderMap, HeaderValue, ACCEPT, CONTENT_TYPE, HOST}; use crate::{body, Client, Method}; - use crate::header::{ACCEPT, HOST, HeaderMap, HeaderValue, CONTENT_TYPE}; - use std::collections::{BTreeMap, HashMap}; use serde::Serialize; use serde_json; use serde_urlencoded; + use std::collections::{BTreeMap, HashMap}; #[test] fn basic_get_request() { @@ -755,7 +748,10 @@ mod tests { let some_url = "https://google.com/"; let mut r = client.get(some_url); - let params = Params { foo: "bar".into(), qux: 3 }; + let params = Params { + foo: "bar".into(), + qux: 3, + }; r = r.query(¶ms); @@ -791,7 +787,10 @@ mod tests { let mut r = r.form(&form_data).build().unwrap(); // Make sure the content type was set - assert_eq!(r.headers().get(CONTENT_TYPE).unwrap(), &"application/x-www-form-urlencoded"); + assert_eq!( + r.headers().get(CONTENT_TYPE).unwrap(), + &"application/x-www-form-urlencoded" + ); let buf = body::read_to_string(r.body_mut().take().unwrap()).unwrap(); @@ -821,15 +820,16 @@ mod tests { #[test] fn add_json_fail() { - use serde::{Serialize, Serializer}; use serde::ser::Error; + use serde::{Serialize, Serializer}; struct MyStruct; impl Serialize for MyStruct { fn serialize(&self, _serializer: S) -> Result - where S: Serializer - { - Err(S::Error::custom("nope")) - } + where + S: Serializer, + { + Err(S::Error::custom("nope")) + } } let client = Client::new(); @@ -858,11 +858,7 @@ mod tests { assert_eq!(req.headers()["im-a"], "keeper"); - let foo = req - .headers() - .get_all("foo") - .iter() - .collect::>(); + let foo = req.headers().get_all("foo").iter().collect::>(); assert_eq!(foo.len(), 2); assert_eq!(foo[0], "bar"); assert_eq!(foo[1], "baz"); diff --git a/src/response.rs b/src/response.rs index 754b7ac..46cbcda 100644 --- a/src/response.rs +++ b/src/response.rs @@ -1,6 +1,6 @@ -use std::mem; use std::fmt; use std::io::{self, Read}; +use std::mem; use std::net::SocketAddr; use std::time::Duration; @@ -8,10 +8,10 @@ use futures::{Async, Poll, Stream}; use http; use serde::de::DeserializeOwned; -use crate::cookie; use crate::client::KeepCoreThreadAlive; +use crate::cookie; +use crate::{async_impl, wait, StatusCode, Url, Version}; use hyper::header::HeaderMap; -use crate::{async_impl, StatusCode, Url, Version, wait}; /// A Response to a submitted `Request`. pub struct Response { @@ -28,7 +28,11 @@ impl fmt::Debug for Response { } impl Response { - pub(crate) fn new(res: async_impl::Response, timeout: Option, thread: KeepCoreThreadAlive) -> Response { + pub(crate) fn new( + res: async_impl::Response, + timeout: Option, + thread: KeepCoreThreadAlive, + ) -> Response { Response { inner: res, body: None, @@ -116,12 +120,10 @@ impl Response { /// Retrieve the cookies contained in the response. /// /// Note that invalid 'Set-Cookie' headers will be ignored. - pub fn cookies<'a>(&'a self) -> impl Iterator< Item = cookie::Cookie<'a> > + 'a { - cookie::extract_response_cookies(self.headers()) - .filter_map(Result::ok) + pub fn cookies<'a>(&'a self) -> impl Iterator> + 'a { + cookie::extract_response_cookies(self.headers()).filter_map(Result::ok) } - /// Get the HTTP `Version` of this `Response`. #[inline] pub fn version(&self) -> Version { @@ -202,12 +204,10 @@ impl Response { /// [`serde_json::from_reader`]: https://docs.serde.rs/serde_json/fn.from_reader.html #[inline] pub fn json(&mut self) -> crate::Result { - wait::timeout(self.inner.json(), self.timeout).map_err(|e| { - match e { - wait::Waited::TimedOut => crate::error::timedout(None), - wait::Waited::Executor(e) => crate::error::from(e), - wait::Waited::Inner(e) => e, - } + wait::timeout(self.inner.json(), self.timeout).map_err(|e| match e { + wait::Waited::TimedOut => crate::error::timedout(None), + wait::Waited::Executor(e) => crate::error::from(e), + wait::Waited::Inner(e) => e, }) } @@ -291,7 +291,8 @@ impl Response { /// ``` #[inline] pub fn copy_to(&mut self, w: &mut W) -> crate::Result - where W: io::Write + where + W: io::Write, { io::copy(self, w).map_err(crate::error::from) } @@ -314,14 +315,17 @@ impl Response { /// ``` #[inline] pub fn error_for_status(self) -> crate::Result { - let Response { body, inner, timeout, _thread_handle } = self; - inner.error_for_status().map(move |inner| { - Response { - inner, - body, - timeout, - _thread_handle, - } + let Response { + body, + inner, + timeout, + _thread_handle, + } = self; + inner.error_for_status().map(move |inner| Response { + inner, + body, + timeout, + _thread_handle, }) } @@ -353,7 +357,7 @@ impl Read for Response { if self.body.is_none() { let body = mem::replace(self.inner.body_mut(), async_impl::Decoder::empty()); let body = async_impl::ReadableChunks::new(WaitBody { - inner: wait::stream(body, self.timeout) + inner: wait::stream(body, self.timeout), }); self.body = Some(body); } @@ -365,7 +369,7 @@ impl Read for Response { } struct WaitBody { - inner: wait::WaitStream + inner: wait::WaitStream, } impl Stream for WaitBody { @@ -383,7 +387,7 @@ impl Stream for WaitBody { }; Err(req_err) - }, + } None => Ok(Async::Ready(None)), } } diff --git a/src/tls.rs b/src/tls.rs index 0d174bc..9fa3946 100644 --- a/src/tls.rs +++ b/src/tls.rs @@ -1,6 +1,6 @@ -use std::fmt; #[cfg(feature = "rustls-tls")] -use rustls::{TLSError, ServerCertVerifier, RootCertStore, ServerCertVerified}; +use rustls::{RootCertStore, ServerCertVerified, ServerCertVerifier, TLSError}; +use std::fmt; #[cfg(feature = "rustls-tls")] use tokio_rustls::webpki::DNSNameRef; @@ -17,7 +17,7 @@ pub struct Certificate { #[derive(Clone)] enum Cert { Der(Vec), - Pem(Vec) + Pem(Vec), } /// Represent a private key and X509 cert as a client certificate. @@ -32,7 +32,7 @@ enum ClientCert { Pem { key: rustls::PrivateKey, certs: Vec, - } + }, } impl Certificate { @@ -61,7 +61,6 @@ impl Certificate { }) } - /// Create a `Certificate` from a PEM encoded certificate /// /// # Examples @@ -83,36 +82,32 @@ impl Certificate { #[cfg(feature = "default-tls")] native: try_!(native_tls::Certificate::from_pem(pem)), #[cfg(feature = "rustls-tls")] - original: Cert::Pem(pem.to_owned()) + original: Cert::Pem(pem.to_owned()), }) } #[cfg(feature = "default-tls")] - pub(crate) fn add_to_native_tls( - self, - tls: &mut native_tls::TlsConnectorBuilder, - ) { + pub(crate) fn add_to_native_tls(self, tls: &mut native_tls::TlsConnectorBuilder) { tls.add_root_certificate(self.native); } #[cfg(feature = "rustls-tls")] - pub(crate) fn add_to_rustls( - self, - tls: &mut rustls::ClientConfig, - ) -> crate::Result<()> { - use std::io::Cursor; + pub(crate) fn add_to_rustls(self, tls: &mut rustls::ClientConfig) -> crate::Result<()> { use rustls::internal::pemfile; + use std::io::Cursor; match self.original { - Cert::Der(buf) => try_!(tls.root_store.add(&::rustls::Certificate(buf)) + Cert::Der(buf) => try_!(tls + .root_store + .add(&::rustls::Certificate(buf)) .map_err(TLSError::WebPKIError)), Cert::Pem(buf) => { let mut pem = Cursor::new(buf); - let certs = try_!(pemfile::certs(&mut pem) - .map_err(|_| TLSError::General(String::from("No valid certificate was found")))); + let certs = try_!(pemfile::certs(&mut pem).map_err(|_| TLSError::General( + String::from("No valid certificate was found") + ))); for c in certs { - try_!(tls.root_store.add(&c) - .map_err(TLSError::WebPKIError)); + try_!(tls.root_store.add(&c).map_err(TLSError::WebPKIError)); } } } @@ -151,9 +146,7 @@ impl Identity { #[cfg(feature = "default-tls")] pub fn from_pkcs12_der(der: &[u8], password: &str) -> crate::Result { Ok(Identity { - inner: ClientCert::Pkcs12( - try_!(native_tls::Identity::from_pkcs12(der, password)) - ), + inner: ClientCert::Pkcs12(try_!(native_tls::Identity::from_pkcs12(der, password))), }) } @@ -178,8 +171,8 @@ impl Identity { /// ``` #[cfg(feature = "rustls-tls")] pub fn from_pem(buf: &[u8]) -> crate::Result { - use std::io::Cursor; use rustls::internal::pemfile; + use std::io::Cursor; let (key, certs) = { let mut pem = Cursor::new(buf); @@ -202,15 +195,14 @@ impl Identity { if let (Some(sk), false) = (sk.pop(), certs.is_empty()) { (sk, certs) } else { - return Err(crate::error::from(TLSError::General(String::from("private key or certificate not found")))); + return Err(crate::error::from(TLSError::General(String::from( + "private key or certificate not found", + )))); } }; Ok(Identity { - inner: ClientCert::Pem { - key, - certs, - }, + inner: ClientCert::Pem { key, certs }, }) } @@ -223,39 +215,34 @@ impl Identity { ClientCert::Pkcs12(id) => { tls.identity(id); Ok(()) - }, + } #[cfg(feature = "rustls-tls")] - ClientCert::Pem { .. } => Err(crate::error::from(crate::error::Kind::TlsIncompatible)) + ClientCert::Pem { .. } => Err(crate::error::from(crate::error::Kind::TlsIncompatible)), } } #[cfg(feature = "rustls-tls")] - pub(crate) fn add_to_rustls( - self, - tls: &mut rustls::ClientConfig, - ) -> crate::Result<()> { + pub(crate) fn add_to_rustls(self, tls: &mut rustls::ClientConfig) -> crate::Result<()> { match self.inner { ClientCert::Pem { key, certs } => { tls.set_single_client_cert(certs, key); Ok(()) - }, + } #[cfg(feature = "default-tls")] - ClientCert::Pkcs12(..) => Err(crate::error::from(crate::error::Kind::TlsIncompatible)) + ClientCert::Pkcs12(..) => Err(crate::error::from(crate::error::Kind::TlsIncompatible)), } } } impl fmt::Debug for Certificate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Certificate") - .finish() + f.debug_struct("Certificate").finish() } } impl fmt::Debug for Identity { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Identity") - .finish() + f.debug_struct("Identity").finish() } } @@ -263,16 +250,20 @@ pub(crate) enum TlsBackend { #[cfg(feature = "default-tls")] Default, #[cfg(feature = "rustls-tls")] - Rustls + Rustls, } impl Default for TlsBackend { fn default() -> TlsBackend { #[cfg(feature = "default-tls")] - { TlsBackend::Default } + { + TlsBackend::Default + } #[cfg(all(feature = "rustls-tls", not(feature = "default-tls")))] - { TlsBackend::Rustls } + { + TlsBackend::Rustls + } } } @@ -286,7 +277,7 @@ impl ServerCertVerifier for NoVerifier { _roots: &RootCertStore, _presented_certs: &[rustls::Certificate], _dns_name: DNSNameRef, - _ocsp_response: &[u8] + _ocsp_response: &[u8], ) -> Result { Ok(ServerCertVerified::assertion()) } diff --git a/src/wait.rs b/src/wait.rs index 36861a5..9beb41b 100644 --- a/src/wait.rs +++ b/src/wait.rs @@ -2,8 +2,8 @@ use std::sync::Arc; use std::thread; use std::time::{Duration, Instant}; -use futures::{Async, Future, Poll, Stream}; use futures::executor::{self, Notify}; +use futures::{Async, Future, Poll, Stream}; use tokio_executor::{enter, EnterError}; pub(crate) fn timeout(fut: F, timeout: Option) -> Result> @@ -11,13 +11,13 @@ where F: Future, { let mut spawn = executor::spawn(fut); - block_on(timeout, |notify| { - spawn.poll_future_notify(notify, 0) - }) + block_on(timeout, |notify| spawn.poll_future_notify(notify, 0)) } pub(crate) fn stream(stream: S, timeout: Option) -> WaitStream -where S: Stream { +where + S: Stream, +{ WaitStream { stream: executor::spawn(stream), timeout, @@ -43,7 +43,9 @@ pub(crate) struct WaitStream { } impl Iterator for WaitStream -where S: Stream { +where + S: Stream, +{ type Item = Result>; fn next(&mut self) -> Option { @@ -74,9 +76,7 @@ where F: FnMut(&Arc) -> Poll, { let _entered = enter().map_err(Waited::Executor)?; - let deadline = timeout.map(|d| { - Instant::now() + d - }); + let deadline = timeout.map(|d| Instant::now() + d); let notify = Arc::new(ThreadNotify { thread: thread::current(), }); @@ -99,5 +99,3 @@ where } } } - - diff --git a/tests/async.rs b/tests/async.rs index a0e95e1..64073a7 100644 --- a/tests/async.rs +++ b/tests/async.rs @@ -1,10 +1,3 @@ -extern crate futures; -extern crate libflate; -extern crate reqwest; -extern crate hyper; -extern crate tokio; -extern crate bytes; - #[macro_use] mod support; @@ -14,8 +7,8 @@ use std::time::Duration; use futures::{Future, Stream}; use tokio::runtime::current_thread::Runtime; -use reqwest::r#async::{Chunk, Client}; use reqwest::r#async::multipart::{Form, Part}; +use reqwest::r#async::{Chunk, Client}; use bytes::Bytes; @@ -54,7 +47,8 @@ fn response_text() { let client = Client::new(); - let res_future = client.get(&format!("http://{}/text", server.addr())) + let res_future = client + .get(&format!("http://{}/text", server.addr())) .send() .and_then(|mut res| res.text()) .and_then(|text| { @@ -90,7 +84,8 @@ fn response_json() { let client = Client::new(); - let res_future = client.get(&format!("http://{}/json", server.addr())) + let res_future = client + .get(&format!("http://{}/json", server.addr())) .send() .and_then(|mut res| res.json::()) .and_then(|text| { @@ -105,34 +100,36 @@ fn response_json() { fn multipart() { let _ = env_logger::try_init(); - let stream = futures::stream::once::<_, hyper::Error>(Ok(Chunk::from("part1 part2".to_owned()))); + let stream = + futures::stream::once::<_, hyper::Error>(Ok(Chunk::from("part1 part2".to_owned()))); let part = Part::stream(stream); - let form = Form::new() - .text("foo", "bar") - .part("part_stream", part); + let form = Form::new().text("foo", "bar").part("part_stream", part); - let expected_body = format!("\ - 24\r\n\ - --{0}\r\n\r\n\ - 2E\r\n\ - Content-Disposition: form-data; name=\"foo\"\r\n\r\n\r\n\ - 3\r\n\ - bar\r\n\ - 2\r\n\ - \r\n\r\n\ - 24\r\n\ - --{0}\r\n\r\n\ - 36\r\n\ - Content-Disposition: form-data; name=\"part_stream\"\r\n\r\n\r\n\ - B\r\n\ - part1 part2\r\n\ - 2\r\n\ - \r\n\r\n\ - 26\r\n\ - --{0}--\r\n\r\n\ - 0\r\n\r\n\ - ", form.boundary()); + let expected_body = format!( + "\ + 24\r\n\ + --{0}\r\n\r\n\ + 2E\r\n\ + Content-Disposition: form-data; name=\"foo\"\r\n\r\n\r\n\ + 3\r\n\ + bar\r\n\ + 2\r\n\ + \r\n\r\n\ + 24\r\n\ + --{0}\r\n\r\n\ + 36\r\n\ + Content-Disposition: form-data; name=\"part_stream\"\r\n\r\n\r\n\ + B\r\n\ + part1 part2\r\n\ + 2\r\n\ + \r\n\r\n\ + 26\r\n\ + --{0}--\r\n\r\n\ + 0\r\n\r\n\ + ", + form.boundary() + ); let server = server! { request: format!("\ @@ -160,15 +157,12 @@ fn multipart() { let client = Client::new(); - let res_future = client.post(&url) - .multipart(form) - .send() - .and_then(|res| { - assert_eq!(res.url().as_str(), &url); - assert_eq!(res.status(), reqwest::StatusCode::OK); + let res_future = client.post(&url).multipart(form).send().and_then(|res| { + assert_eq!(res.url().as_str(), &url); + assert_eq!(res.status(), reqwest::StatusCode::OK); - Ok(()) - }); + Ok(()) + }); rt.block_on(res_future).unwrap(); } @@ -203,9 +197,7 @@ fn request_timeout() { .unwrap(); let url = format!("http://{}/slow", server.addr()); - let fut = client - .get(&url) - .send(); + let fut = client.get(&url).send(); let err = rt.block_on(fut).unwrap_err(); @@ -254,7 +246,10 @@ fn response_timeout() { } fn gzip_case(response_size: usize, chunk_size: usize) { - let content: String = (0..response_size).into_iter().map(|i| format!("test {}", i)).collect(); + let content: String = (0..response_size) + .into_iter() + .map(|i| format!("test {}", i)) + .collect(); let mut encoder = libflate::gzip::Encoder::new(Vec::new()).unwrap(); match encoder.write(content.as_bytes()) { Ok(n) => assert!(n > 0, "Failed to write to encoder."), @@ -263,13 +258,16 @@ fn gzip_case(response_size: usize, chunk_size: usize) { let gzipped_content = encoder.finish().into_result().unwrap(); - let mut response = format!("\ - HTTP/1.1 200 OK\r\n\ - Server: test-accept\r\n\ - Content-Encoding: gzip\r\n\ - Content-Length: {}\r\n\ - \r\n", &gzipped_content.len()) - .into_bytes(); + let mut response = format!( + "\ + HTTP/1.1 200 OK\r\n\ + Server: test-accept\r\n\ + Content-Encoding: gzip\r\n\ + Content-Length: {}\r\n\ + \r\n", + &gzipped_content.len() + ) + .into_bytes(); response.extend(&gzipped_content); let server = server! { @@ -290,7 +288,8 @@ fn gzip_case(response_size: usize, chunk_size: usize) { let client = Client::new(); - let res_future = client.get(&format!("http://{}/gzip", server.addr())) + let res_future = client + .get(&format!("http://{}/gzip", server.addr())) .send() .and_then(|res| { let body = res.into_body(); @@ -311,9 +310,11 @@ fn gzip_case(response_size: usize, chunk_size: usize) { fn body_stream() { let _ = env_logger::try_init(); - let source: Box + Send> - = Box::new(futures::stream::iter_ok::<_, io::Error>( - vec![Bytes::from_static(b"123"), Bytes::from_static(b"4567")])); + let source: Box + Send> = + Box::new(futures::stream::iter_ok::<_, io::Error>(vec![ + Bytes::from_static(b"123"), + Bytes::from_static(b"4567"), + ])); let expected_body = "3\r\n123\r\n4\r\n4567\r\n0\r\n\r\n"; @@ -342,15 +343,12 @@ fn body_stream() { let client = Client::new(); - let res_future = client.post(&url) - .body(source) - .send() - .and_then(|res| { - assert_eq!(res.url().as_str(), &url); - assert_eq!(res.status(), reqwest::StatusCode::OK); + let res_future = client.post(&url).body(source).send().and_then(|res| { + assert_eq!(res.url().as_str(), &url); + assert_eq!(res.status(), reqwest::StatusCode::OK); - Ok(()) - }); + Ok(()) + }); rt.block_on(res_future).unwrap(); } diff --git a/tests/badssl.rs b/tests/badssl.rs index da6fe11..eb843f5 100644 --- a/tests/badssl.rs +++ b/tests/badssl.rs @@ -1,11 +1,10 @@ -extern crate reqwest; - - #[cfg(feature = "tls")] #[test] fn test_badssl_modern() { - let text = reqwest::get("https://mozilla-modern.badssl.com/").unwrap() - .text().unwrap(); + let text = reqwest::get("https://mozilla-modern.badssl.com/") + .unwrap() + .text() + .unwrap(); assert!(text.contains("mozilla-modern.badssl.com")); } @@ -15,10 +14,13 @@ fn test_badssl_modern() { fn test_rustls_badssl_modern() { let text = reqwest::Client::builder() .use_rustls_tls() - .build().unwrap() + .build() + .unwrap() .get("https://mozilla-modern.badssl.com/") - .send().unwrap() - .text().unwrap(); + .send() + .unwrap() + .text() + .unwrap(); assert!(text.contains("mozilla-modern.badssl.com")); } @@ -28,10 +30,13 @@ fn test_rustls_badssl_modern() { fn test_badssl_self_signed() { let text = reqwest::Client::builder() .danger_accept_invalid_certs(true) - .build().unwrap() + .build() + .unwrap() .get("https://self-signed.badssl.com/") - .send().unwrap() - .text().unwrap(); + .send() + .unwrap() + .text() + .unwrap(); assert!(text.contains("self-signed.badssl.com")); } @@ -41,17 +46,20 @@ fn test_badssl_self_signed() { fn test_badssl_wrong_host() { let text = reqwest::Client::builder() .danger_accept_invalid_hostnames(true) - .build().unwrap() + .build() + .unwrap() .get("https://wrong.host.badssl.com/") - .send().unwrap() - .text().unwrap(); + .send() + .unwrap() + .text() + .unwrap(); assert!(text.contains("wrong.host.badssl.com")); - let result = reqwest::Client::builder() .danger_accept_invalid_hostnames(true) - .build().unwrap() + .build() + .unwrap() .get("https://self-signed.badssl.com/") .send(); diff --git a/tests/client.rs b/tests/client.rs index b5ee6c9..6f1bdf4 100644 --- a/tests/client.rs +++ b/tests/client.rs @@ -1,5 +1,3 @@ -extern crate reqwest; - #[macro_use] mod support; @@ -30,7 +28,10 @@ fn test_response_text() { assert_eq!(res.url().as_str(), &url); assert_eq!(res.status(), reqwest::StatusCode::OK); assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test"); - assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"5"); + assert_eq!( + res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), + &"5" + ); let body = res.text().unwrap(); assert_eq!(b"Hello", body.as_bytes()); @@ -62,11 +63,14 @@ fn test_response_non_utf_8_text() { assert_eq!(res.url().as_str(), &url); assert_eq!(res.status(), reqwest::StatusCode::OK); assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test"); - assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"4"); + assert_eq!( + res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), + &"4" + ); let body = res.text().unwrap(); assert_eq!("你好", &body); - assert_eq!(b"\xe4\xbd\xa0\xe5\xa5\xbd", body.as_bytes()); // Now it's utf-8 + assert_eq!(b"\xe4\xbd\xa0\xe5\xa5\xbd", body.as_bytes()); // Now it's utf-8 } #[test] @@ -94,7 +98,10 @@ fn test_response_json() { assert_eq!(res.url().as_str(), &url); assert_eq!(res.status(), reqwest::StatusCode::OK); assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test"); - assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"7"); + assert_eq!( + res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), + &"7" + ); let body = res.json::().unwrap(); assert_eq!("Hello", body); @@ -125,7 +132,10 @@ fn test_response_copy_to() { assert_eq!(res.url().as_str(), &url); assert_eq!(res.status(), reqwest::StatusCode::OK); assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test"); - assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"5"); + assert_eq!( + res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), + &"5" + ); let mut buf: Vec = vec![]; res.copy_to(&mut buf).unwrap(); @@ -157,7 +167,10 @@ fn test_get() { assert_eq!(res.url().as_str(), &url); assert_eq!(res.status(), reqwest::StatusCode::OK); assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test"); - assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"0"); + assert_eq!( + res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), + &"0" + ); assert_eq!(res.remote_addr(), Some(server.addr())); let mut buf = [0; 1024]; @@ -196,7 +209,10 @@ fn test_post() { assert_eq!(res.url().as_str(), &url); assert_eq!(res.status(), reqwest::StatusCode::OK); assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"post"); - assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"0"); + assert_eq!( + res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), + &"0" + ); let mut buf = [0; 1024]; let n = res.read(&mut buf).unwrap(); @@ -293,7 +309,10 @@ fn test_error_for_status_5xx() { let err = res.error_for_status().err().unwrap(); assert!(err.is_server_error()); - assert_eq!(err.status(), Some(reqwest::StatusCode::INTERNAL_SERVER_ERROR)); + assert_eq!( + err.status(), + Some(reqwest::StatusCode::INTERNAL_SERVER_ERROR) + ); } #[test] @@ -303,7 +322,8 @@ fn test_default_headers() { headers.insert(header::COOKIE, header::HeaderValue::from_static("a=b;c=d")); let client = reqwest::Client::builder() .default_headers(headers) - .build().unwrap(); + .build() + .unwrap(); let server = server! { request: b"\ @@ -329,7 +349,10 @@ fn test_default_headers() { assert_eq!(res.url().as_str(), &url); assert_eq!(res.status(), reqwest::StatusCode::OK); assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test"); - assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"0"); + assert_eq!( + res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), + &"0" + ); let server = server! { request: b"\ @@ -355,17 +378,24 @@ fn test_default_headers() { assert_eq!(res.url().as_str(), &url); assert_eq!(res.status(), reqwest::StatusCode::OK); assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test"); - assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"0"); + assert_eq!( + res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), + &"0" + ); } #[test] fn test_override_default_headers() { use reqwest::header; let mut headers = header::HeaderMap::with_capacity(1); - headers.insert(header::AUTHORIZATION, header::HeaderValue::from_static("iamatoken")); + headers.insert( + header::AUTHORIZATION, + header::HeaderValue::from_static("iamatoken"), + ); let client = reqwest::Client::builder() .default_headers(headers) - .build().unwrap(); + .build() + .unwrap(); let server = server! { request: b"\ @@ -386,13 +416,22 @@ fn test_override_default_headers() { }; let url = format!("http://{}/3", server.addr()); - let res = client.get(&url).header(header::AUTHORIZATION, header::HeaderValue::from_static("secret")).send().unwrap(); + let res = client + .get(&url) + .header( + header::AUTHORIZATION, + header::HeaderValue::from_static("secret"), + ) + .send() + .unwrap(); assert_eq!(res.url().as_str(), &url); assert_eq!(res.status(), reqwest::StatusCode::OK); assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test"); - assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"0"); - + assert_eq!( + res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), + &"0" + ); } #[test] @@ -418,20 +457,32 @@ fn test_appended_headers_not_overwritten() { }; let url = format!("http://{}/4", server.addr()); - let res = client.get(&url).header(header::ACCEPT, "application/json").header(header::ACCEPT, "application/json+hal").send().unwrap(); + let res = client + .get(&url) + .header(header::ACCEPT, "application/json") + .header(header::ACCEPT, "application/json+hal") + .send() + .unwrap(); assert_eq!(res.url().as_str(), &url); assert_eq!(res.status(), reqwest::StatusCode::OK); assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test"); - assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"0"); + assert_eq!( + res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), + &"0" + ); // make sure this also works with default headers use reqwest::header; let mut headers = header::HeaderMap::with_capacity(1); - headers.insert(header::ACCEPT, header::HeaderValue::from_static("text/html")); + headers.insert( + header::ACCEPT, + header::HeaderValue::from_static("text/html"), + ); let client = reqwest::Client::builder() .default_headers(headers) - .build().unwrap(); + .build() + .unwrap(); let server = server! { request: b"\ @@ -452,10 +503,18 @@ fn test_appended_headers_not_overwritten() { }; let url = format!("http://{}/4", server.addr()); - let res = client.get(&url).header(header::ACCEPT, "application/json").header(header::ACCEPT, "application/json+hal").send().unwrap(); + let res = client + .get(&url) + .header(header::ACCEPT, "application/json") + .header(header::ACCEPT, "application/json+hal") + .send() + .unwrap(); assert_eq!(res.url().as_str(), &url); assert_eq!(res.status(), reqwest::StatusCode::OK); assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test"); - assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"0"); + assert_eq!( + res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), + &"0" + ); } diff --git a/tests/cookie.rs b/tests/cookie.rs index 8e91c47..a7198c9 100644 --- a/tests/cookie.rs +++ b/tests/cookie.rs @@ -1,5 +1,3 @@ -extern crate reqwest; - #[macro_use] mod support; @@ -45,7 +43,7 @@ fn cookie_response_accessor() { // expires assert_eq!(cookies[1].name(), "expires"); assert_eq!( - cookies[1].expires().unwrap(), + cookies[1].expires().unwrap(), std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(1445412480) ); @@ -55,7 +53,10 @@ fn cookie_response_accessor() { // max-age assert_eq!(cookies[3].name(), "maxage"); - assert_eq!(cookies[3].max_age().unwrap(), std::time::Duration::from_secs(100)); + assert_eq!( + cookies[3].max_age().unwrap(), + std::time::Duration::from_secs(100) + ); // domain assert_eq!(cookies[4].name(), "domain"); @@ -81,7 +82,10 @@ fn cookie_response_accessor() { #[test] fn cookie_store_simple() { let mut rt = tokio::runtime::current_thread::Runtime::new().expect("new rt"); - let client = reqwest::r#async::Client::builder().cookie_store(true).build().unwrap(); + let client = reqwest::r#async::Client::builder() + .cookie_store(true) + .build() + .unwrap(); let server = server! { request: b"\ @@ -125,7 +129,10 @@ fn cookie_store_simple() { #[test] fn cookie_store_overwrite_existing() { let mut rt = tokio::runtime::current_thread::Runtime::new().expect("new rt"); - let client = reqwest::r#async::Client::builder().cookie_store(true).build().unwrap(); + let client = reqwest::r#async::Client::builder() + .cookie_store(true) + .build() + .unwrap(); let server = server! { request: b"\ @@ -189,7 +196,10 @@ fn cookie_store_overwrite_existing() { #[test] fn cookie_store_max_age() { let mut rt = tokio::runtime::current_thread::Runtime::new().expect("new rt"); - let client = reqwest::r#async::Client::builder().cookie_store(true).build().unwrap(); + let client = reqwest::r#async::Client::builder() + .cookie_store(true) + .build() + .unwrap(); let server = server! { request: b"\ @@ -232,7 +242,10 @@ fn cookie_store_max_age() { #[test] fn cookie_store_expires() { let mut rt = tokio::runtime::current_thread::Runtime::new().expect("new rt"); - let client = reqwest::r#async::Client::builder().cookie_store(true).build().unwrap(); + let client = reqwest::r#async::Client::builder() + .cookie_store(true) + .build() + .unwrap(); let server = server! { request: b"\ @@ -275,7 +288,10 @@ fn cookie_store_expires() { #[test] fn cookie_store_path() { let mut rt = tokio::runtime::current_thread::Runtime::new().expect("new rt"); - let client = reqwest::r#async::Client::builder().cookie_store(true).build().unwrap(); + let client = reqwest::r#async::Client::builder() + .cookie_store(true) + .build() + .unwrap(); let server = server! { request: b"\ diff --git a/tests/gzip.rs b/tests/gzip.rs index 4a373be..f6d7578 100644 --- a/tests/gzip.rs +++ b/tests/gzip.rs @@ -1,11 +1,8 @@ -extern crate reqwest; -extern crate libflate; - #[macro_use] mod support; -use std::time::Duration; use std::io::{Read, Write}; +use std::time::Duration; #[test] fn test_gzip_response() { @@ -19,13 +16,16 @@ fn test_gzip_response() { let gzipped_content = encoder.finish().into_result().unwrap(); - let mut response = format!("\ - HTTP/1.1 200 OK\r\n\ - Server: test-accept\r\n\ - Content-Encoding: gzip\r\n\ - Content-Length: {}\r\n\ - \r\n", &gzipped_content.len()) - .into_bytes(); + let mut response = format!( + "\ + HTTP/1.1 200 OK\r\n\ + Server: test-accept\r\n\ + Content-Encoding: gzip\r\n\ + Content-Length: {}\r\n\ + \r\n", + &gzipped_content.len() + ) + .into_bytes(); response.extend(&gzipped_content); let server = server! { @@ -130,7 +130,10 @@ fn test_accept_header_is_not_changed_if_set() { let res = client .get(&format!("http://{}/accept", server.addr())) - .header(reqwest::header::ACCEPT, reqwest::header::HeaderValue::from_static("application/json")) + .header( + reqwest::header::ACCEPT, + reqwest::header::HeaderValue::from_static("application/json"), + ) .send() .unwrap(); @@ -157,8 +160,12 @@ fn test_accept_encoding_header_is_not_changed_if_set() { }; let client = reqwest::Client::new(); - let res = client.get(&format!("http://{}/accept-encoding", server.addr())) - .header(reqwest::header::ACCEPT_ENCODING, reqwest::header::HeaderValue::from_static("identity")) + let res = client + .get(&format!("http://{}/accept-encoding", server.addr())) + .header( + reqwest::header::ACCEPT_ENCODING, + reqwest::header::HeaderValue::from_static("identity"), + ) .send() .unwrap(); diff --git a/tests/multipart.rs b/tests/multipart.rs index 8e85d0d..0d68bd9 100644 --- a/tests/multipart.rs +++ b/tests/multipart.rs @@ -1,6 +1,3 @@ -extern crate env_logger; -extern crate reqwest; - #[macro_use] mod support; @@ -8,15 +5,17 @@ mod support; fn text_part() { let _ = env_logger::try_init(); - let form = reqwest::multipart::Form::new() - .text("foo", "bar"); + let form = reqwest::multipart::Form::new().text("foo", "bar"); - let expected_body = format!("\ - --{0}\r\n\ - Content-Disposition: form-data; name=\"foo\"\r\n\r\n\ - bar\r\n\ - --{0}--\r\n\ - ", form.boundary()); + let expected_body = format!( + "\ + --{0}\r\n\ + Content-Disposition: form-data; name=\"foo\"\r\n\r\n\ + bar\r\n\ + --{0}--\r\n\ + ", + form.boundary() + ); let server = server! { request: format!("\ @@ -55,17 +54,22 @@ fn file() { let _ = env_logger::try_init(); let form = reqwest::multipart::Form::new() - .file("foo", "Cargo.lock").unwrap(); + .file("foo", "Cargo.lock") + .unwrap(); let fcontents = std::fs::read_to_string("Cargo.lock").unwrap(); - let expected_body = format!("\ - --{0}\r\n\ - Content-Disposition: form-data; name=\"foo\"; filename=\"Cargo.lock\"\r\n\ - Content-Type: application/octet-stream\r\n\r\n\ - {1}\r\n\ - --{0}--\r\n\ - ", form.boundary(), fcontents); + let expected_body = format!( + "\ + --{0}\r\n\ + Content-Disposition: form-data; name=\"foo\"; filename=\"Cargo.lock\"\r\n\ + Content-Type: application/octet-stream\r\n\r\n\ + {1}\r\n\ + --{0}--\r\n\ + ", + form.boundary(), + fcontents + ); let server = server! { request: format!("\ diff --git a/tests/proxy.rs b/tests/proxy.rs index 038acde..08f3b99 100644 --- a/tests/proxy.rs +++ b/tests/proxy.rs @@ -1,5 +1,3 @@ -extern crate reqwest; - #[macro_use] mod support; @@ -37,7 +35,10 @@ fn http_proxy() { assert_eq!(res.url().as_str(), url); assert_eq!(res.status(), reqwest::StatusCode::OK); - assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"proxied"); + assert_eq!( + res.headers().get(reqwest::header::SERVER).unwrap(), + &"proxied" + ); } #[test] @@ -66,8 +67,8 @@ fn http_proxy_basic_auth() { let res = reqwest::Client::builder() .proxy( reqwest::Proxy::http(&proxy) - .unwrap() - .basic_auth("Aladdin", "open sesame") + .unwrap() + .basic_auth("Aladdin", "open sesame"), ) .build() .unwrap() @@ -77,7 +78,10 @@ fn http_proxy_basic_auth() { assert_eq!(res.url().as_str(), url); assert_eq!(res.status(), reqwest::StatusCode::OK); - assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"proxied"); + assert_eq!( + res.headers().get(reqwest::header::SERVER).unwrap(), + &"proxied" + ); } #[test] @@ -104,9 +108,7 @@ fn http_proxy_basic_auth_parsed() { let url = "http://hyper.rs/prox"; let res = reqwest::Client::builder() - .proxy( - reqwest::Proxy::http(&proxy).unwrap() - ) + .proxy(reqwest::Proxy::http(&proxy).unwrap()) .build() .unwrap() .get(url) @@ -115,7 +117,10 @@ fn http_proxy_basic_auth_parsed() { assert_eq!(res.url().as_str(), url); assert_eq!(res.status(), reqwest::StatusCode::OK); - assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"proxied"); + assert_eq!( + res.headers().get(reqwest::header::SERVER).unwrap(), + &"proxied" + ); } #[test] @@ -141,9 +146,7 @@ fn test_no_proxy() { // set up proxy and use no_proxy to clear up client builder proxies. let res = reqwest::Client::builder() - .proxy( - reqwest::Proxy::http(&proxy).unwrap() - ) + .proxy(reqwest::Proxy::http(&proxy).unwrap()) .no_proxy() .build() .unwrap() @@ -189,11 +192,14 @@ fn test_using_system_proxy() { assert_eq!(res.url().as_str(), url); assert_eq!(res.status(), reqwest::StatusCode::OK); - assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"proxied"); + assert_eq!( + res.headers().get(reqwest::header::SERVER).unwrap(), + &"proxied" + ); // reset user setting. match system_proxy { Err(_) => env::remove_var("http_proxy"), - Ok(proxy) => env::set_var("http_proxy", proxy) + Ok(proxy) => env::set_var("http_proxy", proxy), } } diff --git a/tests/redirect.rs b/tests/redirect.rs index 9ff1b6f..2da9d32 100644 --- a/tests/redirect.rs +++ b/tests/redirect.rs @@ -1,5 +1,3 @@ -extern crate reqwest; - #[macro_use] mod support; @@ -47,12 +45,13 @@ fn test_redirect_301_and_302_and_303_changes_post_to_get() { let url = format!("http://{}/{}", redirect.addr(), code); let dst = format!("http://{}/{}", redirect.addr(), "dst"); - let res = client.post(&url) - .send() - .unwrap(); + let res = client.post(&url).send().unwrap(); assert_eq!(res.url().as_str(), dst); assert_eq!(res.status(), reqwest::StatusCode::OK); - assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test-dst"); + assert_eq!( + res.headers().get(reqwest::header::SERVER).unwrap(), + &"test-dst" + ); } } @@ -99,12 +98,13 @@ fn test_redirect_307_and_308_tries_to_get_again() { let url = format!("http://{}/{}", redirect.addr(), code); let dst = format!("http://{}/{}", redirect.addr(), "dst"); - let res = client.get(&url) - .send() - .unwrap(); + let res = client.get(&url).send().unwrap(); assert_eq!(res.url().as_str(), dst); assert_eq!(res.status(), reqwest::StatusCode::OK); - assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test-dst"); + assert_eq!( + res.headers().get(reqwest::header::SERVER).unwrap(), + &"test-dst" + ); } } @@ -155,13 +155,13 @@ fn test_redirect_307_and_308_tries_to_post_again() { let url = format!("http://{}/{}", redirect.addr(), code); let dst = format!("http://{}/{}", redirect.addr(), "dst"); - let res = client.post(&url) - .body("Hello") - .send() - .unwrap(); + let res = client.post(&url).body("Hello").send().unwrap(); assert_eq!(res.url().as_str(), dst); assert_eq!(res.status(), reqwest::StatusCode::OK); - assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test-dst"); + assert_eq!( + res.headers().get(reqwest::header::SERVER).unwrap(), + &"test-dst" + ); } } @@ -204,8 +204,6 @@ fn test_redirect_307_does_not_try_if_reader_cannot_reset() { } } - - #[test] fn test_redirect_removes_sensitive_headers() { let end_server = server! { @@ -249,7 +247,10 @@ fn test_redirect_removes_sensitive_headers() { .build() .unwrap() .get(&format!("http://{}/sensitive", mid_server.addr())) - .header(reqwest::header::COOKIE, reqwest::header::HeaderValue::from_static("foo=bar")) + .header( + reqwest::header::COOKIE, + reqwest::header::HeaderValue::from_static("foo=bar"), + ) .send() .unwrap(); } @@ -310,7 +311,10 @@ fn test_redirect_policy_can_stop_redirects_without_an_error() { assert_eq!(res.url().as_str(), url); assert_eq!(res.status(), reqwest::StatusCode::FOUND); - assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test-dont"); + assert_eq!( + res.headers().get(reqwest::header::SERVER).unwrap(), + &"test-dont" + ); } #[test] @@ -385,58 +389,65 @@ fn test_invalid_location_stops_redirect_gh484() { assert_eq!(res.url().as_str(), url); assert_eq!(res.status(), reqwest::StatusCode::FOUND); - assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test-yikes"); + assert_eq!( + res.headers().get(reqwest::header::SERVER).unwrap(), + &"test-yikes" + ); } #[test] fn test_redirect_302_with_set_cookies() { let code = 302; - let client = reqwest::ClientBuilder::new().cookie_store(true).build().unwrap(); + let client = reqwest::ClientBuilder::new() + .cookie_store(true) + .build() + .unwrap(); let server = server! { - request: format!("\ - GET /{} HTTP/1.1\r\n\ - user-agent: $USERAGENT\r\n\ - accept: */*\r\n\ - accept-encoding: gzip\r\n\ - host: $HOST\r\n\ - \r\n\ - ", code), - response: format!("\ - HTTP/1.1 {} reason\r\n\ - Server: test-redirect\r\n\ - Content-Length: 0\r\n\ - Location: /dst\r\n\ - Connection: close\r\n\ - Set-Cookie: key=value\r\n\ - \r\n\ - ", code) - ; + request: format!("\ + GET /{} HTTP/1.1\r\n\ + user-agent: $USERAGENT\r\n\ + accept: */*\r\n\ + accept-encoding: gzip\r\n\ + host: $HOST\r\n\ + \r\n\ + ", code), + response: format!("\ + HTTP/1.1 {} reason\r\n\ + Server: test-redirect\r\n\ + Content-Length: 0\r\n\ + Location: /dst\r\n\ + Connection: close\r\n\ + Set-Cookie: key=value\r\n\ + \r\n\ + ", code) + ; - request: format!("\ - GET /dst HTTP/1.1\r\n\ - user-agent: $USERAGENT\r\n\ - accept: */*\r\n\ - accept-encoding: gzip\r\n\ - referer: http://$HOST/{}\r\n\ - cookie: key=value\r\n\ - host: $HOST\r\n\ - \r\n\ - ", code), - response: b"\ - HTTP/1.1 200 OK\r\n\ - Server: test-dst\r\n\ - Content-Length: 0\r\n\ - \r\n\ - " - }; + request: format!("\ + GET /dst HTTP/1.1\r\n\ + user-agent: $USERAGENT\r\n\ + accept: */*\r\n\ + accept-encoding: gzip\r\n\ + referer: http://$HOST/{}\r\n\ + cookie: key=value\r\n\ + host: $HOST\r\n\ + \r\n\ + ", code), + response: b"\ + HTTP/1.1 200 OK\r\n\ + Server: test-dst\r\n\ + Content-Length: 0\r\n\ + \r\n\ + " + }; let url = format!("http://{}/{}", server.addr(), code); let dst = format!("http://{}/{}", server.addr(), "dst"); - let res = client.get(&url) - .send() - .unwrap(); + let res = client.get(&url).send().unwrap(); assert_eq!(res.url().as_str(), dst); assert_eq!(res.status(), reqwest::StatusCode::OK); - assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test-dst"); + assert_eq!( + res.headers().get(reqwest::header::SERVER).unwrap(), + &"test-dst" + ); } diff --git a/tests/support/server.rs b/tests/support/server.rs index bb43736..ecee108 100644 --- a/tests/support/server.rs +++ b/tests/support/server.rs @@ -2,9 +2,9 @@ use std::io::{Read, Write}; use std::net; -use std::time::Duration; use std::sync::mpsc; use std::thread; +use std::time::Duration; pub struct Server { addr: net::SocketAddr, @@ -19,9 +19,8 @@ impl Server { impl Drop for Server { fn drop(&mut self) { - if !::std::thread::panicking() { - self - .panic_rx + if !thread::panicking() { + self.panic_rx .recv_timeout(Duration::from_secs(3)) .expect("test server should not panic"); } @@ -47,7 +46,10 @@ pub fn spawn(txns: Vec) -> Server { let listener = net::TcpListener::bind("127.0.0.1:0").unwrap(); let addr = listener.local_addr().unwrap(); let (panic_tx, panic_rx) = mpsc::channel(); - let tname = format!("test({})-support-server", thread::current().name().unwrap_or("")); + let tname = format!( + "test({})-support-server", + thread::current().name().unwrap_or("") + ); thread::Builder::new().name(tname).spawn(move || { 'txns: for txn in txns { let mut expected = txn.request; @@ -149,10 +151,7 @@ pub fn spawn(txns: Vec) -> Server { let _ = panic_tx.send(()); }).expect("server thread spawn"); - Server { - addr, - panic_rx, - } + Server { addr, panic_rx } } fn replace_expected_vars(bytes: &mut Vec, host: &[u8], ua: &[u8]) { @@ -210,16 +209,15 @@ macro_rules! __internal__txn { ) } - #[macro_export] macro_rules! __internal__prop { - (request: $val:expr) => ( + (request: $val:expr) => { From::from(&$val[..]) - ); - (response: $val:expr) => ( + }; + (response: $val:expr) => { From::from(&$val[..]) - ); - ($field:ident: $val:expr) => ( + }; + ($field:ident: $val:expr) => { From::from($val) - ) + }; } diff --git a/tests/timeouts.rs b/tests/timeouts.rs index 0fd7f5f..0c57eae 100644 --- a/tests/timeouts.rs +++ b/tests/timeouts.rs @@ -1,6 +1,3 @@ -extern crate env_logger; -extern crate reqwest; - #[macro_use] mod support; @@ -38,10 +35,7 @@ fn timeout_closes_connection() { }; let url = format!("http://{}/closes", server.addr()); - let err = client - .get(&url) - .send() - .unwrap_err(); + let err = client.get(&url).send().unwrap_err(); assert_eq!(err.get_ref().unwrap().to_string(), "timed out"); assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str())); @@ -93,7 +87,6 @@ fn write_timeout_large_body() { assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str())); } - #[test] fn test_response_timeout() { let _ = env_logger::try_init(); @@ -158,7 +151,10 @@ fn test_read_timeout() { assert_eq!(res.url().as_str(), &url); assert_eq!(res.status(), reqwest::StatusCode::OK); - assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"5"); + assert_eq!( + res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), + &"5" + ); let mut buf = [0; 1024]; let err = res.read(&mut buf).unwrap_err();