committed by
Sean McArthur
parent
7bd3619ece
commit
c417d6dab8
18
Cargo.toml
18
Cargo.toml
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.8.6" # remember to update html_root_url
|
version = "0.9.0-pre" # remember to update html_root_url
|
||||||
description = "higher level HTTP client library"
|
description = "higher level HTTP client library"
|
||||||
keywords = ["http", "request", "client"]
|
keywords = ["http", "request", "client"]
|
||||||
repository = "https://github.com/seanmonstar/reqwest"
|
repository = "https://github.com/seanmonstar/reqwest"
|
||||||
@@ -9,20 +9,26 @@ authors = ["Sean McArthur <sean@seanmonstar.com>"]
|
|||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
categories = ["web-programming::http-client"]
|
categories = ["web-programming::http-client"]
|
||||||
|
|
||||||
|
publish = false # pre
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
base64 = "~0.6.0"
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
encoding_rs = "0.7"
|
encoding_rs = "0.7"
|
||||||
futures = "0.1.15"
|
futures = "0.1.21"
|
||||||
hyper = "0.11.22"
|
http = "0.1.5"
|
||||||
hyper-tls = "0.1.2"
|
hyper = "0.12.2"
|
||||||
|
hyper-tls = "0.2.1"
|
||||||
libflate = "0.1.11"
|
libflate = "0.1.11"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
mime_guess = "2.0.0-alpha.2"
|
mime = "0.3.7"
|
||||||
|
mime_guess = "2.0.0-alpha.4"
|
||||||
native-tls = "0.1.5"
|
native-tls = "0.1.5"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde_urlencoded = "0.5"
|
serde_urlencoded = "0.5"
|
||||||
tokio-core = "0.1.6"
|
tokio-core = "0.1.17"
|
||||||
|
tokio = "0.1.7"
|
||||||
tokio-io = "0.1"
|
tokio-io = "0.1"
|
||||||
tokio-tls = "0.1"
|
tokio-tls = "0.1"
|
||||||
url = "1.2"
|
url = "1.2"
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ error_chain! {
|
|||||||
|
|
||||||
fn run() -> Result<()> {
|
fn run() -> Result<()> {
|
||||||
let mut core = tokio_core::reactor::Core::new()?;
|
let mut core = tokio_core::reactor::Core::new()?;
|
||||||
let client = Client::new(&core.handle());
|
let client = Client::new();
|
||||||
|
|
||||||
let work = client.get("https://hyper.rs")
|
let work = client.get("https://hyper.rs")
|
||||||
.send()
|
.send()
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ fn run() -> Result<()> {
|
|||||||
let mut res = reqwest::get("https://www.rust-lang.org/en-US/")?;
|
let mut res = reqwest::get("https://www.rust-lang.org/en-US/")?;
|
||||||
|
|
||||||
println!("Status: {}", res.status());
|
println!("Status: {}", res.status());
|
||||||
println!("Headers:\n{}", res.headers());
|
println!("Headers:\n{:?}", res.headers());
|
||||||
|
|
||||||
// copy the response body directly to stdout
|
// copy the response body directly to stdout
|
||||||
let _ = std::io::copy(&mut res, &mut std::io::stdout())?;
|
let _ = std::io::copy(&mut res, &mut std::io::stdout())?;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use std::fmt;
|
|||||||
|
|
||||||
use futures::{Stream, Poll, Async};
|
use futures::{Stream, Poll, Async};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
use hyper::body::Payload;
|
||||||
|
|
||||||
/// An asynchronous `Stream`.
|
/// An asynchronous `Stream`.
|
||||||
pub struct Body {
|
pub struct Body {
|
||||||
@@ -20,6 +21,13 @@ impl Body {
|
|||||||
Inner::Reusable(_) => unreachable!(),
|
Inner::Reusable(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn content_length(&self) -> Option<u64> {
|
||||||
|
match self.inner {
|
||||||
|
Inner::Reusable(ref bytes) => Some(bytes.len() as u64),
|
||||||
|
Inner::Hyper(ref body) => body.content_length(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stream for Body {
|
impl Stream for Body {
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ use std::time::Duration;
|
|||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::{Async, Future, Poll};
|
use futures::{Async, Future, Poll};
|
||||||
use hyper::client::FutureResponse;
|
use hyper::client::ResponseFuture;
|
||||||
use hyper::header::{Headers, Location, Referer, UserAgent, Accept, Encoding,
|
use header::{HeaderMap, HeaderValue, LOCATION, USER_AGENT, REFERER, ACCEPT,
|
||||||
AcceptEncoding, Range, qitem};
|
ACCEPT_ENCODING, RANGE};
|
||||||
|
use mime::{self};
|
||||||
use native_tls::{TlsConnector, TlsConnectorBuilder};
|
use native_tls::{TlsConnector, TlsConnectorBuilder};
|
||||||
use tokio_core::reactor::Handle;
|
|
||||||
|
|
||||||
|
|
||||||
use super::body;
|
use super::body;
|
||||||
@@ -63,7 +63,7 @@ pub struct ClientBuilder {
|
|||||||
|
|
||||||
struct Config {
|
struct Config {
|
||||||
gzip: bool,
|
gzip: bool,
|
||||||
headers: Headers,
|
headers: HeaderMap,
|
||||||
hostname_verification: bool,
|
hostname_verification: bool,
|
||||||
proxies: Vec<Proxy>,
|
proxies: Vec<Proxy>,
|
||||||
redirect_policy: RedirectPolicy,
|
redirect_policy: RedirectPolicy,
|
||||||
@@ -78,9 +78,9 @@ impl ClientBuilder {
|
|||||||
pub fn new() -> ClientBuilder {
|
pub fn new() -> ClientBuilder {
|
||||||
match TlsConnector::builder() {
|
match TlsConnector::builder() {
|
||||||
Ok(tls_connector_builder) => {
|
Ok(tls_connector_builder) => {
|
||||||
let mut headers = Headers::with_capacity(2);
|
let mut headers: HeaderMap<HeaderValue> = HeaderMap::with_capacity(2);
|
||||||
headers.set(UserAgent::new(DEFAULT_USER_AGENT));
|
headers.insert(USER_AGENT, HeaderValue::from_static(DEFAULT_USER_AGENT));
|
||||||
headers.set(Accept::star());
|
headers.insert(ACCEPT, HeaderValue::from_str(mime::STAR_STAR.as_ref()).expect("unable to parse mime"));
|
||||||
|
|
||||||
ClientBuilder {
|
ClientBuilder {
|
||||||
config: Some(Config {
|
config: Some(Config {
|
||||||
@@ -114,7 +114,7 @@ impl ClientBuilder {
|
|||||||
///
|
///
|
||||||
/// This method consumes the internal state of the builder.
|
/// This method consumes the internal state of the builder.
|
||||||
/// Trying to use this builder again after calling `build` will panic.
|
/// Trying to use this builder again after calling `build` will panic.
|
||||||
pub fn build(&mut self, handle: &Handle) -> ::Result<Client> {
|
pub fn build(&mut self) -> ::Result<Client> {
|
||||||
if let Some(err) = self.err.take() {
|
if let Some(err) = self.err.take() {
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
@@ -126,14 +126,13 @@ impl ClientBuilder {
|
|||||||
|
|
||||||
let proxies = Arc::new(config.proxies);
|
let proxies = Arc::new(config.proxies);
|
||||||
|
|
||||||
let mut connector = Connector::new(config.dns_threads, tls, proxies.clone(), handle);
|
let mut connector = Connector::new(config.dns_threads, tls, proxies.clone());
|
||||||
if !config.hostname_verification {
|
if !config.hostname_verification {
|
||||||
connector.danger_disable_hostname_verification();
|
connector.danger_disable_hostname_verification();
|
||||||
}
|
}
|
||||||
|
|
||||||
let hyper_client = ::hyper::Client::configure()
|
let hyper_client = ::hyper::Client::builder()
|
||||||
.connector(connector)
|
.build(connector);
|
||||||
.build(handle);
|
|
||||||
|
|
||||||
Ok(Client {
|
Ok(Client {
|
||||||
inner: Arc::new(ClientRef {
|
inner: Arc::new(ClientRef {
|
||||||
@@ -200,9 +199,11 @@ impl ClientBuilder {
|
|||||||
|
|
||||||
/// Sets the default headers for every request.
|
/// Sets the default headers for every request.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn default_headers(&mut self, headers: Headers) -> &mut ClientBuilder {
|
pub fn default_headers(&mut self, headers: HeaderMap) -> &mut ClientBuilder {
|
||||||
if let Some(config) = config_mut(&mut self.config, &self.err) {
|
if let Some(config) = config_mut(&mut self.config, &self.err) {
|
||||||
config.headers.extend(headers.iter());
|
for (key, value) in headers.iter() {
|
||||||
|
config.headers.insert(key, value.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@@ -287,9 +288,9 @@ impl Client {
|
|||||||
/// initialized. Use `Client::builder()` if you wish to handle the failure
|
/// initialized. Use `Client::builder()` if you wish to handle the failure
|
||||||
/// as an `Error` instead of panicking.
|
/// as an `Error` instead of panicking.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(handle: &Handle) -> Client {
|
pub fn new() -> Client {
|
||||||
ClientBuilder::new()
|
ClientBuilder::new()
|
||||||
.build(handle)
|
.build()
|
||||||
.expect("TLS failed to initialize")
|
.expect("TLS failed to initialize")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,7 +306,7 @@ impl Client {
|
|||||||
///
|
///
|
||||||
/// This method fails whenever supplied `Url` cannot be parsed.
|
/// This method fails whenever supplied `Url` cannot be parsed.
|
||||||
pub fn get<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
pub fn get<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
||||||
self.request(Method::Get, url)
|
self.request(Method::GET, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience method to make a `POST` request to a URL.
|
/// Convenience method to make a `POST` request to a URL.
|
||||||
@@ -314,7 +315,7 @@ impl Client {
|
|||||||
///
|
///
|
||||||
/// This method fails whenever supplied `Url` cannot be parsed.
|
/// This method fails whenever supplied `Url` cannot be parsed.
|
||||||
pub fn post<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
pub fn post<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
||||||
self.request(Method::Post, url)
|
self.request(Method::POST, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience method to make a `PUT` request to a URL.
|
/// Convenience method to make a `PUT` request to a URL.
|
||||||
@@ -323,7 +324,7 @@ impl Client {
|
|||||||
///
|
///
|
||||||
/// This method fails whenever supplied `Url` cannot be parsed.
|
/// This method fails whenever supplied `Url` cannot be parsed.
|
||||||
pub fn put<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
pub fn put<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
||||||
self.request(Method::Put, url)
|
self.request(Method::PUT, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience method to make a `PATCH` request to a URL.
|
/// Convenience method to make a `PATCH` request to a URL.
|
||||||
@@ -332,7 +333,7 @@ impl Client {
|
|||||||
///
|
///
|
||||||
/// This method fails whenever supplied `Url` cannot be parsed.
|
/// This method fails whenever supplied `Url` cannot be parsed.
|
||||||
pub fn patch<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
pub fn patch<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
||||||
self.request(Method::Patch, url)
|
self.request(Method::PATCH, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience method to make a `DELETE` request to a URL.
|
/// Convenience method to make a `DELETE` request to a URL.
|
||||||
@@ -341,7 +342,7 @@ impl Client {
|
|||||||
///
|
///
|
||||||
/// This method fails whenever supplied `Url` cannot be parsed.
|
/// This method fails whenever supplied `Url` cannot be parsed.
|
||||||
pub fn delete<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
pub fn delete<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
||||||
self.request(Method::Delete, url)
|
self.request(Method::DELETE, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience method to make a `HEAD` request to a URL.
|
/// Convenience method to make a `HEAD` request to a URL.
|
||||||
@@ -350,7 +351,7 @@ impl Client {
|
|||||||
///
|
///
|
||||||
/// This method fails whenever supplied `Url` cannot be parsed.
|
/// This method fails whenever supplied `Url` cannot be parsed.
|
||||||
pub fn head<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
pub fn head<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
||||||
self.request(Method::Head, url)
|
self.request(Method::HEAD, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start building a `Request` with the `Method` and `Url`.
|
/// Start building a `Request` with the `Method` and `Url`.
|
||||||
@@ -395,28 +396,35 @@ impl Client {
|
|||||||
) = request::pieces(req);
|
) = request::pieces(req);
|
||||||
|
|
||||||
let mut headers = self.inner.headers.clone(); // default headers
|
let mut headers = self.inner.headers.clone(); // default headers
|
||||||
headers.extend(user_headers.iter());
|
for (key, value) in user_headers.iter() {
|
||||||
|
headers.insert(key, value.clone());
|
||||||
|
}
|
||||||
|
|
||||||
if self.inner.gzip &&
|
if self.inner.gzip &&
|
||||||
!headers.has::<AcceptEncoding>() &&
|
!headers.contains_key(ACCEPT_ENCODING) &&
|
||||||
!headers.has::<Range>() {
|
!headers.contains_key(RANGE) {
|
||||||
headers.set(AcceptEncoding(vec![qitem(Encoding::Gzip)]));
|
headers.insert(ACCEPT_ENCODING, HeaderValue::from_static("gzip"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let uri = to_uri(&url);
|
let uri = to_uri(&url);
|
||||||
let mut req = ::hyper::Request::new(method.clone(), uri.clone());
|
|
||||||
*req.headers_mut() = headers.clone();
|
|
||||||
let body = body.map(|body| {
|
|
||||||
let (reusable, body) = body::into_hyper(body);
|
|
||||||
req.set_body(body);
|
|
||||||
reusable
|
|
||||||
});
|
|
||||||
|
|
||||||
if proxy::is_proxied(&self.inner.proxies, &url) {
|
let (reusable, body) = match body {
|
||||||
if uri.scheme() == Some("http") {
|
Some(body) => {
|
||||||
req.set_proxy(true);
|
let (reusable, body) = body::into_hyper(body);
|
||||||
|
(Some(reusable), body)
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
(None, ::hyper::Body::empty())
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
let mut req = ::hyper::Request::builder()
|
||||||
|
.method(method.clone())
|
||||||
|
.uri(uri.clone())
|
||||||
|
.body(body)
|
||||||
|
.expect("valid request parts");
|
||||||
|
|
||||||
|
*req.headers_mut() = headers.clone();
|
||||||
|
|
||||||
let in_flight = self.inner.hyper.request(req);
|
let in_flight = self.inner.hyper.request(req);
|
||||||
|
|
||||||
@@ -425,7 +433,7 @@ impl Client {
|
|||||||
method: method,
|
method: method,
|
||||||
url: url,
|
url: url,
|
||||||
headers: headers,
|
headers: headers,
|
||||||
body: body,
|
body: reusable,
|
||||||
|
|
||||||
urls: Vec::new(),
|
urls: Vec::new(),
|
||||||
|
|
||||||
@@ -456,7 +464,7 @@ impl fmt::Debug for ClientBuilder {
|
|||||||
|
|
||||||
struct ClientRef {
|
struct ClientRef {
|
||||||
gzip: bool,
|
gzip: bool,
|
||||||
headers: Headers,
|
headers: HeaderMap,
|
||||||
hyper: HyperClient,
|
hyper: HyperClient,
|
||||||
proxies: Arc<Vec<Proxy>>,
|
proxies: Arc<Vec<Proxy>>,
|
||||||
redirect_policy: RedirectPolicy,
|
redirect_policy: RedirectPolicy,
|
||||||
@@ -475,14 +483,14 @@ enum PendingInner {
|
|||||||
pub struct PendingRequest {
|
pub struct PendingRequest {
|
||||||
method: Method,
|
method: Method,
|
||||||
url: Url,
|
url: Url,
|
||||||
headers: Headers,
|
headers: HeaderMap,
|
||||||
body: Option<Option<Bytes>>,
|
body: Option<Option<Bytes>>,
|
||||||
|
|
||||||
urls: Vec<Url>,
|
urls: Vec<Url>,
|
||||||
|
|
||||||
client: Arc<ClientRef>,
|
client: Arc<ClientRef>,
|
||||||
|
|
||||||
in_flight: FutureResponse,
|
in_flight: ResponseFuture,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -509,20 +517,20 @@ impl Future for PendingRequest {
|
|||||||
Async::NotReady => return Ok(Async::NotReady),
|
Async::NotReady => return Ok(Async::NotReady),
|
||||||
};
|
};
|
||||||
let should_redirect = match res.status() {
|
let should_redirect = match res.status() {
|
||||||
StatusCode::MovedPermanently |
|
StatusCode::MOVED_PERMANENTLY |
|
||||||
StatusCode::Found |
|
StatusCode::FOUND |
|
||||||
StatusCode::SeeOther => {
|
StatusCode::SEE_OTHER => {
|
||||||
self.body = None;
|
self.body = None;
|
||||||
match self.method {
|
match self.method {
|
||||||
Method::Get | Method::Head => {},
|
Method::GET | Method::HEAD => {},
|
||||||
_ => {
|
_ => {
|
||||||
self.method = Method::Get;
|
self.method = Method::GET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
},
|
},
|
||||||
StatusCode::TemporaryRedirect |
|
StatusCode::TEMPORARY_REDIRECT |
|
||||||
StatusCode::PermanentRedirect => match self.body {
|
StatusCode::PERMANENT_REDIRECT => match self.body {
|
||||||
Some(Some(_)) | None => true,
|
Some(Some(_)) | None => true,
|
||||||
Some(None) => false,
|
Some(None) => false,
|
||||||
},
|
},
|
||||||
@@ -530,12 +538,12 @@ impl Future for PendingRequest {
|
|||||||
};
|
};
|
||||||
if should_redirect {
|
if should_redirect {
|
||||||
let loc = res.headers()
|
let loc = res.headers()
|
||||||
.get::<Location>()
|
.get(LOCATION)
|
||||||
.map(|loc| self.url.join(loc));
|
.map(|loc| self.url.join(loc.to_str().expect("")));
|
||||||
if let Some(Ok(loc)) = loc {
|
if let Some(Ok(loc)) = loc {
|
||||||
if self.client.referer {
|
if self.client.referer {
|
||||||
if let Some(referer) = make_referer(&loc, &self.url) {
|
if let Some(referer) = make_referer(&loc, &self.url) {
|
||||||
self.headers.set(referer);
|
self.headers.insert(REFERER, referer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.urls.push(self.url.clone());
|
self.urls.push(self.url.clone());
|
||||||
@@ -553,19 +561,17 @@ impl Future for PendingRequest {
|
|||||||
remove_sensitive_headers(&mut self.headers, &self.url, &self.urls);
|
remove_sensitive_headers(&mut self.headers, &self.url, &self.urls);
|
||||||
debug!("redirecting to {:?} '{}'", self.method, self.url);
|
debug!("redirecting to {:?} '{}'", self.method, self.url);
|
||||||
let uri = to_uri(&self.url);
|
let uri = to_uri(&self.url);
|
||||||
let mut req = ::hyper::Request::new(
|
let body = match self.body {
|
||||||
self.method.clone(),
|
Some(Some(ref body)) => ::hyper::Body::from(body.clone()),
|
||||||
uri.clone()
|
_ => ::hyper::Body::empty(),
|
||||||
);
|
};
|
||||||
|
let mut req = ::hyper::Request::builder()
|
||||||
|
.method(self.method.clone())
|
||||||
|
.uri(uri.clone())
|
||||||
|
.body(body)
|
||||||
|
.expect("valid request parts");
|
||||||
|
|
||||||
*req.headers_mut() = self.headers.clone();
|
*req.headers_mut() = self.headers.clone();
|
||||||
if let Some(Some(ref body)) = self.body {
|
|
||||||
req.set_body(body.clone());
|
|
||||||
}
|
|
||||||
if proxy::is_proxied(&self.client.proxies, &self.url) {
|
|
||||||
if uri.scheme() == Some("http") {
|
|
||||||
req.set_proxy(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.in_flight = self.client.hyper.request(req);
|
self.in_flight = self.client.hyper.request(req);
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
@@ -607,7 +613,7 @@ impl fmt::Debug for Pending {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_referer(next: &Url, previous: &Url) -> Option<Referer> {
|
fn make_referer(next: &Url, previous: &Url) -> Option<HeaderValue> {
|
||||||
if next.scheme() == "http" && previous.scheme() == "https" {
|
if next.scheme() == "http" && previous.scheme() == "https" {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@@ -616,7 +622,7 @@ fn make_referer(next: &Url, previous: &Url) -> Option<Referer> {
|
|||||||
let _ = referer.set_username("");
|
let _ = referer.set_username("");
|
||||||
let _ = referer.set_password(None);
|
let _ = referer.set_password(None);
|
||||||
referer.set_fragment(None);
|
referer.set_fragment(None);
|
||||||
Some(Referer::new(referer.into_string()))
|
referer.as_str().parse().ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub(crate)
|
// pub(crate)
|
||||||
|
|||||||
@@ -33,12 +33,12 @@ use tokio_io::AsyncRead;
|
|||||||
use tokio_io::io as async_io;
|
use tokio_io::io as async_io;
|
||||||
use futures::{Async, Future, Poll, Stream};
|
use futures::{Async, Future, Poll, Stream};
|
||||||
use futures::stream::Concat2;
|
use futures::stream::Concat2;
|
||||||
use hyper::StatusCode;
|
use hyper::{HeaderMap, StatusCode};
|
||||||
|
use hyper::header::{CONTENT_ENCODING, CONTENT_LENGTH, TRANSFER_ENCODING, HeaderValue};
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use header::{Headers, ContentEncoding, ContentLength, Encoding, TransferEncoding};
|
|
||||||
use super::{body, Body, Chunk};
|
use super::{body, Body, Chunk};
|
||||||
use error;
|
use error;
|
||||||
|
|
||||||
@@ -111,6 +111,13 @@ impl Decoder {
|
|||||||
inner: Inner::Pending(Pending::Gzip(ReadableChunks::new(body)))
|
inner: Inner::Pending(Pending::Gzip(ReadableChunks::new(body)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn content_length(&self) -> Option<u64> {
|
||||||
|
match self.inner {
|
||||||
|
Inner::PlainText(ref body) => body.content_length(),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stream for Decoder {
|
impl Stream for Decoder {
|
||||||
@@ -407,31 +414,33 @@ impl<S> ReadableChunks<S>
|
|||||||
/// how to decode the content body of the request.
|
/// how to decode the content body of the request.
|
||||||
///
|
///
|
||||||
/// Uses the correct variant by inspecting the Content-Encoding header.
|
/// Uses the correct variant by inspecting the Content-Encoding header.
|
||||||
pub fn detect(headers: &mut Headers, body: Body, check_gzip: bool) -> Decoder {
|
pub fn detect(headers: &mut HeaderMap, body: Body, check_gzip: bool) -> Decoder {
|
||||||
if !check_gzip {
|
if !check_gzip {
|
||||||
return Decoder::plain_text(body);
|
return Decoder::plain_text(body);
|
||||||
}
|
}
|
||||||
let content_encoding_gzip: bool;
|
let content_encoding_gzip: bool;
|
||||||
let mut is_gzip = {
|
let mut is_gzip = {
|
||||||
content_encoding_gzip = headers
|
content_encoding_gzip = headers
|
||||||
.get::<ContentEncoding>()
|
.get_all(CONTENT_ENCODING)
|
||||||
.map_or(false, |encs| encs.contains(&Encoding::Gzip));
|
.iter()
|
||||||
|
.fold(false, |acc, enc| acc || enc == HeaderValue::from_static("gzip"));
|
||||||
content_encoding_gzip ||
|
content_encoding_gzip ||
|
||||||
headers
|
headers
|
||||||
.get::<TransferEncoding>()
|
.get_all(TRANSFER_ENCODING)
|
||||||
.map_or(false, |encs| encs.contains(&Encoding::Gzip))
|
.iter()
|
||||||
|
.fold(false, |acc, enc| acc || enc == HeaderValue::from_static("gzip"))
|
||||||
};
|
};
|
||||||
if is_gzip {
|
if is_gzip {
|
||||||
if let Some(content_length) = headers.get::<ContentLength>() {
|
if let Some(content_length) = headers.get(CONTENT_LENGTH) {
|
||||||
if content_length.0 == 0 {
|
if content_length == "0" {
|
||||||
warn!("GZipped response with content-length of 0");
|
warn!("GZipped response with content-length of 0");
|
||||||
is_gzip = false;
|
is_gzip = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if content_encoding_gzip {
|
if content_encoding_gzip {
|
||||||
headers.remove::<ContentEncoding>();
|
headers.remove(CONTENT_ENCODING);
|
||||||
headers.remove::<ContentLength>();
|
headers.remove(CONTENT_LENGTH);
|
||||||
}
|
}
|
||||||
if is_gzip {
|
if is_gzip {
|
||||||
Decoder::gzip(body)
|
Decoder::gzip(body)
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
use base64::{encode};
|
||||||
|
use mime::{self};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use serde_urlencoded;
|
use serde_urlencoded;
|
||||||
|
|
||||||
use super::body::{self, Body};
|
use super::body::{self, Body};
|
||||||
use super::client::{Client, Pending, pending_err};
|
use super::client::{Client, Pending, pending_err};
|
||||||
use header::{ContentType, Headers};
|
use header::{CONTENT_TYPE, HeaderMap, HeaderName, HeaderValue};
|
||||||
|
use http::HttpTryFrom;
|
||||||
use {Method, Url};
|
use {Method, Url};
|
||||||
|
|
||||||
/// A request which can be executed with `Client::execute()`.
|
/// A request which can be executed with `Client::execute()`.
|
||||||
pub struct Request {
|
pub struct Request {
|
||||||
method: Method,
|
method: Method,
|
||||||
url: Url,
|
url: Url,
|
||||||
headers: Headers,
|
headers: HeaderMap,
|
||||||
body: Option<Body>,
|
body: Option<Body>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +34,7 @@ impl Request {
|
|||||||
Request {
|
Request {
|
||||||
method,
|
method,
|
||||||
url,
|
url,
|
||||||
headers: Headers::new(),
|
headers: HeaderMap::new(),
|
||||||
body: None,
|
body: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,13 +65,13 @@ impl Request {
|
|||||||
|
|
||||||
/// Get the headers.
|
/// Get the headers.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn headers(&self) -> &Headers {
|
pub fn headers(&self) -> &HeaderMap {
|
||||||
&self.headers
|
&self.headers
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a mutable reference to the headers.
|
/// Get a mutable reference to the headers.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn headers_mut(&mut self) -> &mut Headers {
|
pub fn headers_mut(&mut self) -> &mut HeaderMap {
|
||||||
&mut self.headers
|
&mut self.headers
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,21 +90,32 @@ impl Request {
|
|||||||
|
|
||||||
impl RequestBuilder {
|
impl RequestBuilder {
|
||||||
/// Add a `Header` to this Request.
|
/// Add a `Header` to this Request.
|
||||||
pub fn header<H>(&mut self, header: H) -> &mut RequestBuilder
|
pub fn header<K, V>(&mut self, key: K, value: V) -> &mut RequestBuilder
|
||||||
where
|
where
|
||||||
H: ::header::Header,
|
HeaderName: HttpTryFrom<K>,
|
||||||
|
HeaderValue: HttpTryFrom<V>,
|
||||||
{
|
{
|
||||||
if let Some(req) = request_mut(&mut self.request, &self.err) {
|
if let Some(req) = request_mut(&mut self.request, &self.err) {
|
||||||
req.headers_mut().set(header);
|
match <HeaderName as HttpTryFrom<K>>::try_from(key) {
|
||||||
|
Ok(key) => {
|
||||||
|
match <HeaderValue as HttpTryFrom<V>>::try_from(value) {
|
||||||
|
Ok(value) => { req.headers_mut().append(key, value); }
|
||||||
|
Err(e) => self.err = Some(::error::from(e.into())),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => self.err = Some(::error::from(e.into())),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// Add a set of Headers to the existing ones on this Request.
|
/// Add a set of Headers to the existing ones on this Request.
|
||||||
///
|
///
|
||||||
/// The headers will be merged in to any already set.
|
/// The headers will be merged in to any already set.
|
||||||
pub fn headers(&mut self, headers: ::header::Headers) -> &mut RequestBuilder {
|
pub fn headers(&mut self, headers: ::header::HeaderMap) -> &mut RequestBuilder {
|
||||||
if let Some(req) = request_mut(&mut self.request, &self.err) {
|
if let Some(req) = request_mut(&mut self.request, &self.err) {
|
||||||
req.headers_mut().extend(headers.iter());
|
for (key, value) in headers.iter() {
|
||||||
|
req.headers_mut().insert(key, value.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@@ -112,10 +126,10 @@ impl RequestBuilder {
|
|||||||
U: Into<String>,
|
U: Into<String>,
|
||||||
P: Into<String>,
|
P: Into<String>,
|
||||||
{
|
{
|
||||||
self.header(::header::Authorization(::header::Basic {
|
let username = username.into();
|
||||||
username: username.into(),
|
let password = password.map(|p| p.into()).unwrap_or(String::new());
|
||||||
password: password.map(|p| p.into()),
|
let header_value = format!("basic {}:{}", username, encode(&password));
|
||||||
}))
|
self.header(::header::AUTHORIZATION, HeaderValue::from_str(header_value.as_str()).expect(""))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the request body.
|
/// Set the request body.
|
||||||
@@ -162,7 +176,7 @@ impl RequestBuilder {
|
|||||||
if let Some(req) = request_mut(&mut self.request, &self.err) {
|
if let Some(req) = request_mut(&mut self.request, &self.err) {
|
||||||
match serde_urlencoded::to_string(form) {
|
match serde_urlencoded::to_string(form) {
|
||||||
Ok(body) => {
|
Ok(body) => {
|
||||||
req.headers_mut().set(ContentType::form_url_encoded());
|
req.headers_mut().insert(CONTENT_TYPE, HeaderValue::from_str(mime::APPLICATION_WWW_FORM_URLENCODED.as_ref()).expect(""));
|
||||||
*req.body_mut() = Some(body.into());
|
*req.body_mut() = Some(body.into());
|
||||||
},
|
},
|
||||||
Err(err) => self.err = Some(::error::from(err)),
|
Err(err) => self.err = Some(::error::from(err)),
|
||||||
@@ -181,7 +195,7 @@ impl RequestBuilder {
|
|||||||
if let Some(req) = request_mut(&mut self.request, &self.err) {
|
if let Some(req) = request_mut(&mut self.request, &self.err) {
|
||||||
match serde_json::to_vec(json) {
|
match serde_json::to_vec(json) {
|
||||||
Ok(body) => {
|
Ok(body) => {
|
||||||
req.headers_mut().set(ContentType::json());
|
req.headers_mut().insert(CONTENT_TYPE, HeaderValue::from_str(mime::APPLICATION_JSON.as_ref()).expect(""));
|
||||||
*req.body_mut() = Some(body.into());
|
*req.body_mut() = Some(body.into());
|
||||||
},
|
},
|
||||||
Err(err) => self.err = Some(::error::from(err)),
|
Err(err) => self.err = Some(::error::from(err)),
|
||||||
@@ -274,7 +288,7 @@ pub fn builder(client: Client, req: ::Result<Request>) -> RequestBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn pieces(req: Request) -> (Method, Url, Headers, Option<Body>) {
|
pub fn pieces(req: Request) -> (Method, Url, HeaderMap, Option<Body>) {
|
||||||
(req.method, req.url, req.headers, req.body)
|
(req.method, req.url, req.headers, req.body)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,12 +296,10 @@ pub fn pieces(req: Request) -> (Method, Url, Headers, Option<Body>) {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::Client;
|
use super::Client;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use tokio_core::reactor::Core;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn add_query_append() {
|
fn add_query_append() {
|
||||||
let mut core = Core::new().unwrap();
|
let client = Client::new();
|
||||||
let client = Client::new(&core.handle());
|
|
||||||
let some_url = "https://google.com/";
|
let some_url = "https://google.com/";
|
||||||
let mut r = client.get(some_url);
|
let mut r = client.get(some_url);
|
||||||
|
|
||||||
@@ -300,8 +312,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn add_query_append_same() {
|
fn add_query_append_same() {
|
||||||
let mut core = Core::new().unwrap();
|
let client = Client::new();
|
||||||
let client = Client::new(&core.handle());
|
|
||||||
let some_url = "https://google.com/";
|
let some_url = "https://google.com/";
|
||||||
let mut r = client.get(some_url);
|
let mut r = client.get(some_url);
|
||||||
|
|
||||||
@@ -319,8 +330,7 @@ mod tests {
|
|||||||
qux: i32,
|
qux: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut core = Core::new().unwrap();
|
let client = Client::new();
|
||||||
let client = Client::new(&core.handle());
|
|
||||||
let some_url = "https://google.com/";
|
let some_url = "https://google.com/";
|
||||||
let mut r = client.get(some_url);
|
let mut r = client.get(some_url);
|
||||||
|
|
||||||
@@ -338,8 +348,7 @@ mod tests {
|
|||||||
params.insert("foo", "bar");
|
params.insert("foo", "bar");
|
||||||
params.insert("qux", "three");
|
params.insert("qux", "three");
|
||||||
|
|
||||||
let mut core = Core::new().unwrap();
|
let client = Client::new();
|
||||||
let client = Client::new(&core.handle());
|
|
||||||
let some_url = "https://google.com/";
|
let some_url = "https://google.com/";
|
||||||
let mut r = client.get(some_url);
|
let mut r = client.get(some_url);
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use serde::de::DeserializeOwned;
|
|||||||
use serde_json;
|
use serde_json;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use header::{Headers, ContentEncoding, ContentLength, Encoding, TransferEncoding};
|
use hyper::header::{HeaderMap, CONTENT_ENCODING, CONTENT_LENGTH, TRANSFER_ENCODING};
|
||||||
use super::{decoder, body, Body, Chunk, Decoder};
|
use super::{decoder, body, Body, Chunk, Decoder};
|
||||||
use error;
|
use error;
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ use error;
|
|||||||
/// A Response to a submitted `Request`.
|
/// A Response to a submitted `Request`.
|
||||||
pub struct Response {
|
pub struct Response {
|
||||||
status: StatusCode,
|
status: StatusCode,
|
||||||
headers: Headers,
|
headers: HeaderMap,
|
||||||
url: Url,
|
url: Url,
|
||||||
body: Decoder,
|
body: Decoder,
|
||||||
}
|
}
|
||||||
@@ -41,13 +41,13 @@ impl Response {
|
|||||||
|
|
||||||
/// Get the `Headers` of this `Response`.
|
/// Get the `Headers` of this `Response`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn headers(&self) -> &Headers {
|
pub fn headers(&self) -> &HeaderMap {
|
||||||
&self.headers
|
&self.headers
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a mutable reference to the `Headers` of this `Response`.
|
/// Get a mutable reference to the `Headers` of this `Response`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn headers_mut(&mut self) -> &mut Headers {
|
pub fn headers_mut(&mut self) -> &mut HeaderMap {
|
||||||
&mut self.headers
|
&mut self.headers
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ impl Response {
|
|||||||
/// // it could be any status between 400...599
|
/// // it could be any status between 400...599
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// err.status(),
|
/// err.status(),
|
||||||
/// Some(reqwest::StatusCode::BadRequest)
|
/// Some(reqwest::StatusCode::BAD_REQUEST)
|
||||||
/// );
|
/// );
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
@@ -152,10 +152,10 @@ impl<T> fmt::Debug for Json<T> {
|
|||||||
|
|
||||||
// pub(crate)
|
// pub(crate)
|
||||||
|
|
||||||
pub fn new(mut res: ::hyper::client::Response, url: Url, gzip: bool) -> Response {
|
pub fn new(mut res: ::hyper::Response<::hyper::Body>, url: Url, gzip: bool) -> Response {
|
||||||
let status = res.status();
|
let status = res.status();
|
||||||
let mut headers = mem::replace(res.headers_mut(), Headers::new());
|
let mut headers = mem::replace(res.headers_mut(), HeaderMap::new());
|
||||||
let decoder = decoder::detect(&mut headers, body::wrap(res.body()), gzip);
|
let decoder = decoder::detect(&mut headers, body::wrap(res.into_body()), gzip);
|
||||||
debug!("Response: '{}' for {}", status, url);
|
debug!("Response: '{}' for {}", status, url);
|
||||||
Response {
|
Response {
|
||||||
status: status,
|
status: status,
|
||||||
|
|||||||
21
src/body.rs
21
src/body.rs
@@ -3,9 +3,9 @@ use std::fmt;
|
|||||||
use std::io::{self, Cursor, Read};
|
use std::io::{self, Cursor, Read};
|
||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use hyper::{self, Chunk};
|
use hyper::{self};
|
||||||
|
|
||||||
use {async_impl, wait};
|
use {async_impl};
|
||||||
|
|
||||||
/// The body of a `Request`.
|
/// The body of a `Request`.
|
||||||
///
|
///
|
||||||
@@ -184,7 +184,7 @@ impl Read for Reader {
|
|||||||
|
|
||||||
pub struct Sender {
|
pub struct Sender {
|
||||||
body: (Box<Read + Send>, Option<u64>),
|
body: (Box<Read + Send>, Option<u64>),
|
||||||
tx: wait::WaitSink<::futures::sync::mpsc::Sender<hyper::Result<Chunk>>>,
|
tx: hyper::body::Sender,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sender {
|
impl Sender {
|
||||||
@@ -201,13 +201,8 @@ impl Sender {
|
|||||||
Ok(0) => return Ok(()),
|
Ok(0) => return Ok(()),
|
||||||
Ok(n) => {
|
Ok(n) => {
|
||||||
unsafe { buf.advance_mut(n); }
|
unsafe { buf.advance_mut(n); }
|
||||||
if let Err(e) = tx.send(Ok(buf.take().freeze().into())) {
|
if let Err(_) = tx.send_data(buf.take().freeze().into()) {
|
||||||
if let wait::Waited::Err(_) = e {
|
return Err(::error::timedout(None));
|
||||||
let epipe = io::Error::new(io::ErrorKind::BrokenPipe, "broken pipe");
|
|
||||||
return Err(::error::from(epipe));
|
|
||||||
} else {
|
|
||||||
return Err(::error::timedout(None));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if buf.remaining_mut() == 0 {
|
if buf.remaining_mut() == 0 {
|
||||||
buf.reserve(8192);
|
buf.reserve(8192);
|
||||||
@@ -215,7 +210,7 @@ impl Sender {
|
|||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let ret = io::Error::new(e.kind(), e.to_string());
|
let ret = io::Error::new(e.kind(), e.to_string());
|
||||||
let _ = tx.send(Err(e.into()));
|
tx.abort();
|
||||||
return Err(::error::from(ret));
|
return Err(::error::from(ret));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -227,10 +222,10 @@ impl Sender {
|
|||||||
pub fn async(body: Body) -> (Option<Sender>, async_impl::Body, Option<u64>) {
|
pub fn async(body: Body) -> (Option<Sender>, async_impl::Body, Option<u64>) {
|
||||||
match body.kind {
|
match body.kind {
|
||||||
Kind::Reader(read, len) => {
|
Kind::Reader(read, len) => {
|
||||||
let (tx, rx) = hyper::Body::pair();
|
let (tx, rx) = hyper::Body::channel();
|
||||||
let tx = Sender {
|
let tx = Sender {
|
||||||
body: (read, len),
|
body: (read, len),
|
||||||
tx: wait::sink(tx, None),
|
tx: tx,
|
||||||
};
|
};
|
||||||
(Some(tx), async_impl::body::wrap(rx), len)
|
(Some(tx), async_impl::body::wrap(rx), len)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -174,8 +174,8 @@ impl ClientBuilder {
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
/// use reqwest::header;
|
/// use reqwest::header;
|
||||||
/// # fn build_client() -> Result<(), Box<std::error::Error>> {
|
/// # fn build_client() -> Result<(), Box<std::error::Error>> {
|
||||||
/// let mut headers = header::Headers::new();
|
/// let mut headers = header::HeaderMap::new();
|
||||||
/// headers.set(header::Authorization("secret".to_string()));
|
/// headers.insert(header::AUTHORIZATION, header::HeaderValue::from_static("secret"));
|
||||||
///
|
///
|
||||||
/// // get a client builder
|
/// // get a client builder
|
||||||
/// let client = reqwest::Client::builder()
|
/// let client = reqwest::Client::builder()
|
||||||
@@ -191,8 +191,8 @@ impl ClientBuilder {
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
/// use reqwest::header;
|
/// use reqwest::header;
|
||||||
/// # fn build_client() -> Result<(), Box<std::error::Error>> {
|
/// # fn build_client() -> Result<(), Box<std::error::Error>> {
|
||||||
/// let mut headers = header::Headers::new();
|
/// let mut headers = header::HeaderMap::new();
|
||||||
/// headers.set(header::Authorization("secret".to_string()));
|
/// headers.insert(header::AUTHORIZATION, header::HeaderValue::from_static("secret"));
|
||||||
///
|
///
|
||||||
/// // get a client builder
|
/// // get a client builder
|
||||||
/// let client = reqwest::Client::builder()
|
/// let client = reqwest::Client::builder()
|
||||||
@@ -200,13 +200,13 @@ impl ClientBuilder {
|
|||||||
/// .build()?;
|
/// .build()?;
|
||||||
/// let res = client
|
/// let res = client
|
||||||
/// .get("https://www.rust-lang.org")
|
/// .get("https://www.rust-lang.org")
|
||||||
/// .header(header::Authorization("token".to_string()))
|
/// .header(header::AUTHORIZATION, "token")
|
||||||
/// .send()?;
|
/// .send()?;
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn default_headers(&mut self, headers: header::Headers) -> &mut ClientBuilder {
|
pub fn default_headers(&mut self, headers: header::HeaderMap) -> &mut ClientBuilder {
|
||||||
self.inner.default_headers(headers);
|
self.inner.default_headers(headers);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@@ -287,7 +287,7 @@ impl Client {
|
|||||||
///
|
///
|
||||||
/// This method fails whenever supplied `Url` cannot be parsed.
|
/// This method fails whenever supplied `Url` cannot be parsed.
|
||||||
pub fn get<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
pub fn get<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
||||||
self.request(Method::Get, url)
|
self.request(Method::GET, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience method to make a `POST` request to a URL.
|
/// Convenience method to make a `POST` request to a URL.
|
||||||
@@ -296,7 +296,7 @@ impl Client {
|
|||||||
///
|
///
|
||||||
/// This method fails whenever supplied `Url` cannot be parsed.
|
/// This method fails whenever supplied `Url` cannot be parsed.
|
||||||
pub fn post<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
pub fn post<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
||||||
self.request(Method::Post, url)
|
self.request(Method::POST, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience method to make a `PUT` request to a URL.
|
/// Convenience method to make a `PUT` request to a URL.
|
||||||
@@ -305,7 +305,7 @@ impl Client {
|
|||||||
///
|
///
|
||||||
/// This method fails whenever supplied `Url` cannot be parsed.
|
/// This method fails whenever supplied `Url` cannot be parsed.
|
||||||
pub fn put<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
pub fn put<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
||||||
self.request(Method::Put, url)
|
self.request(Method::PUT, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience method to make a `PATCH` request to a URL.
|
/// Convenience method to make a `PATCH` request to a URL.
|
||||||
@@ -314,7 +314,7 @@ impl Client {
|
|||||||
///
|
///
|
||||||
/// This method fails whenever supplied `Url` cannot be parsed.
|
/// This method fails whenever supplied `Url` cannot be parsed.
|
||||||
pub fn patch<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
pub fn patch<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
||||||
self.request(Method::Patch, url)
|
self.request(Method::PATCH, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience method to make a `DELETE` request to a URL.
|
/// Convenience method to make a `DELETE` request to a URL.
|
||||||
@@ -323,7 +323,7 @@ impl Client {
|
|||||||
///
|
///
|
||||||
/// This method fails whenever supplied `Url` cannot be parsed.
|
/// This method fails whenever supplied `Url` cannot be parsed.
|
||||||
pub fn delete<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
pub fn delete<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
||||||
self.request(Method::Delete, url)
|
self.request(Method::DELETE, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience method to make a `HEAD` request to a URL.
|
/// Convenience method to make a `HEAD` request to a URL.
|
||||||
@@ -332,7 +332,7 @@ impl Client {
|
|||||||
///
|
///
|
||||||
/// This method fails whenever supplied `Url` cannot be parsed.
|
/// This method fails whenever supplied `Url` cannot be parsed.
|
||||||
pub fn head<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
pub fn head<U: IntoUrl>(&self, url: U) -> RequestBuilder {
|
||||||
self.request(Method::Head, url)
|
self.request(Method::HEAD, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start building a `Request` with the `Method` and `Url`.
|
/// Start building a `Request` with the `Method` and `Url`.
|
||||||
@@ -412,22 +412,21 @@ impl ClientHandle {
|
|||||||
let mut builder = async_impl::client::take_builder(&mut builder.inner);
|
let mut builder = async_impl::client::take_builder(&mut builder.inner);
|
||||||
let (tx, rx) = mpsc::unbounded();
|
let (tx, rx) = mpsc::unbounded();
|
||||||
let (spawn_tx, spawn_rx) = oneshot::channel::<::Result<()>>();
|
let (spawn_tx, spawn_rx) = oneshot::channel::<::Result<()>>();
|
||||||
let handle = try_!(thread::Builder::new().name("reqwest-internal-sync-core".into()).spawn(move || {
|
let handle = try_!(thread::Builder::new().name("reqwest-internal-sync-runtime".into()).spawn(move || {
|
||||||
use tokio_core::reactor::Core;
|
use tokio::runtime::current_thread::Runtime;
|
||||||
|
|
||||||
let built = (|| {
|
let built = (|| {
|
||||||
let core = try_!(Core::new());
|
let rt = try_!(Runtime::new());
|
||||||
let handle = core.handle();
|
let client = builder.build()?;
|
||||||
let client = builder.build(&handle)?;
|
Ok((rt, client))
|
||||||
Ok((core, handle, client))
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
let (mut core, handle, client) = match built {
|
let (mut rt, client) = match built {
|
||||||
Ok((a, b, c)) => {
|
Ok((rt, c)) => {
|
||||||
if let Err(_) = spawn_tx.send(Ok(())) {
|
if let Err(_) = spawn_tx.send(Ok(())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(a, b, c)
|
(rt, c)
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let _ = spawn_tx.send(Err(e));
|
let _ = spawn_tx.send(Err(e));
|
||||||
@@ -435,19 +434,22 @@ impl ClientHandle {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let work = rx.for_each(|(req, tx)| {
|
let work = rx.for_each(move |(req, tx)| {
|
||||||
let tx: oneshot::Sender<::Result<async_impl::Response>> = tx;
|
let tx: oneshot::Sender<::Result<async_impl::Response>> = tx;
|
||||||
let task = client.execute(req)
|
let task = client.execute(req)
|
||||||
.then(move |x| tx.send(x).map_err(|_| ()));
|
.then(move |x| tx.send(x).map_err(|_| ()));
|
||||||
handle.spawn(task);
|
::tokio::spawn(task);
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// work is Future<(), ()>, and our closure will never return Err
|
// work is Future<(), ()>, and our closure will never return Err
|
||||||
let _ = core.run(work);
|
rt.spawn(work)
|
||||||
|
.run()
|
||||||
|
.expect("runtime unexpected error");
|
||||||
}));
|
}));
|
||||||
|
|
||||||
wait::timeout(spawn_rx, timeout.0).expect("core thread cancelled")?;
|
wait::timeout(spawn_rx, timeout.0).expect("runtime thread cancelled")?;
|
||||||
|
|
||||||
let inner_handle = Arc::new(InnerClientHandle {
|
let inner_handle = Arc::new(InnerClientHandle {
|
||||||
tx: Some(tx),
|
tx: Some(tx),
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use bytes::{Buf, BufMut, IntoBuf};
|
use bytes::{Buf, BufMut, IntoBuf};
|
||||||
use futures::{Async, Future, Poll};
|
use futures::{Async, Future, Poll};
|
||||||
use hyper::client::{HttpConnector, Service};
|
use http::uri::Scheme;
|
||||||
use hyper::Uri;
|
use hyper::client::{HttpConnector};
|
||||||
|
use hyper::client::connect::{Connect, Connected, Destination};
|
||||||
use hyper_tls::{HttpsConnector, MaybeHttpsStream};
|
use hyper_tls::{HttpsConnector, MaybeHttpsStream};
|
||||||
use native_tls::TlsConnector;
|
use native_tls::TlsConnector;
|
||||||
use tokio_core::reactor::Handle;
|
|
||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
use tokio_tls::{TlsConnectorExt, TlsStream};
|
use tokio_tls::{TlsConnectorExt, TlsStream};
|
||||||
|
|
||||||
@@ -22,8 +22,8 @@ pub struct Connector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Connector {
|
impl Connector {
|
||||||
pub fn new(threads: usize, tls: TlsConnector, proxies: Arc<Vec<Proxy>>, handle: &Handle) -> Connector {
|
pub fn new(threads: usize, tls: TlsConnector, proxies: Arc<Vec<Proxy>>) -> Connector {
|
||||||
let mut http = HttpConnector::new(threads, handle);
|
let mut http = HttpConnector::new(threads);
|
||||||
http.enforce_http(false);
|
http.enforce_http(false);
|
||||||
let https = HttpsConnector::from((http, tls.clone()));
|
let https = HttpsConnector::from((http, tls.clone()));
|
||||||
|
|
||||||
@@ -39,41 +39,53 @@ impl Connector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Service for Connector {
|
impl Connect for Connector {
|
||||||
type Request = Uri;
|
type Transport = Conn;
|
||||||
type Response = Conn;
|
|
||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
type Future = Connecting;
|
type Future = Connecting;
|
||||||
|
|
||||||
fn call(&self, uri: Uri) -> Self::Future {
|
fn connect(&self, dst: Destination) -> Self::Future {
|
||||||
for prox in self.proxies.iter() {
|
for prox in self.proxies.iter() {
|
||||||
if let Some(puri) = proxy::intercept(prox, &uri) {
|
if let Some(puri) = proxy::intercept(prox, &dst) {
|
||||||
trace!("proxy({:?}) intercepts {:?}", puri, uri);
|
trace!("proxy({:?}) intercepts {:?}", puri, dst);
|
||||||
if uri.scheme() == Some("https") {
|
let mut ndst = dst.clone();
|
||||||
let host = uri.host().unwrap().to_owned();
|
let new_scheme = puri
|
||||||
let port = uri.port().unwrap_or(443);
|
.scheme_part()
|
||||||
|
.map(Scheme::as_str)
|
||||||
|
.unwrap_or("http");
|
||||||
|
ndst.set_scheme(new_scheme)
|
||||||
|
.expect("proxy target scheme should be valid");
|
||||||
|
|
||||||
|
ndst.set_host(puri.host().expect("proxy target should have host"))
|
||||||
|
.expect("proxy target host should be valid");
|
||||||
|
|
||||||
|
ndst.set_port(puri.port());
|
||||||
|
|
||||||
|
if dst.scheme() == "https" {
|
||||||
|
let host = dst.host().to_owned();
|
||||||
|
let port = dst.port().unwrap_or(443);
|
||||||
let tls = self.tls.clone();
|
let tls = self.tls.clone();
|
||||||
return Box::new(self.https.call(puri).and_then(move |conn| {
|
return Box::new(self.https.connect(ndst).and_then(move |(conn, connected)| {
|
||||||
trace!("tunneling HTTPS over proxy");
|
trace!("tunneling HTTPS over proxy");
|
||||||
tunnel(conn, host.clone(), port)
|
tunnel(conn, host.clone(), port)
|
||||||
.and_then(move |tunneled| {
|
.and_then(move |tunneled| {
|
||||||
tls.connect_async(&host, tunneled)
|
tls.connect_async(&host, tunneled)
|
||||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))
|
||||||
})
|
})
|
||||||
.map(|io| Conn::Proxied(io))
|
.map(|io| (Conn::Proxied(io), connected.proxy(true)))
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return Box::new(self.https.call(puri).map(|io| Conn::Normal(io)));
|
return Box::new(self.https.connect(ndst).map(|(io, connected)| (Conn::Normal(io), connected.proxy(true))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Box::new(self.https.call(uri).map(|io| Conn::Normal(io)))
|
Box::new(self.https.connect(dst).map(|(io, connected)| (Conn::Normal(io), connected)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type HttpStream = <HttpConnector as Service>::Response;
|
type HttpStream = <HttpConnector as Connect>::Transport;
|
||||||
type HttpsStream = MaybeHttpsStream<HttpStream>;
|
type HttpsStream = MaybeHttpsStream<HttpStream>;
|
||||||
|
|
||||||
pub type Connecting = Box<Future<Item=Conn, Error=io::Error>>;
|
pub type Connecting = Box<Future<Item=(Conn, Connected), Error=io::Error> + Send>;
|
||||||
|
|
||||||
pub enum Conn {
|
pub enum Conn {
|
||||||
Normal(HttpsStream),
|
Normal(HttpsStream),
|
||||||
@@ -214,8 +226,8 @@ mod tests {
|
|||||||
use std::net::TcpListener;
|
use std::net::TcpListener;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
use tokio_core::reactor::Core;
|
use tokio::runtime::current_thread::Runtime;
|
||||||
use tokio_core::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
use super::tunnel;
|
use super::tunnel;
|
||||||
|
|
||||||
|
|
||||||
@@ -251,44 +263,44 @@ mod tests {
|
|||||||
fn test_tunnel() {
|
fn test_tunnel() {
|
||||||
let addr = mock_tunnel!();
|
let addr = mock_tunnel!();
|
||||||
|
|
||||||
let mut core = Core::new().unwrap();
|
let mut rt = Runtime::new().unwrap();
|
||||||
let work = TcpStream::connect(&addr, &core.handle());
|
let work = TcpStream::connect(&addr);
|
||||||
let host = addr.ip().to_string();
|
let host = addr.ip().to_string();
|
||||||
let port = addr.port();
|
let port = addr.port();
|
||||||
let work = work.and_then(|tcp| {
|
let work = work.and_then(|tcp| {
|
||||||
tunnel(tcp, host, port)
|
tunnel(tcp, host, port)
|
||||||
});
|
});
|
||||||
|
|
||||||
core.run(work).unwrap();
|
rt.block_on(work).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_tunnel_eof() {
|
fn test_tunnel_eof() {
|
||||||
let addr = mock_tunnel!(b"HTTP/1.1 200 OK");
|
let addr = mock_tunnel!(b"HTTP/1.1 200 OK");
|
||||||
|
|
||||||
let mut core = Core::new().unwrap();
|
let mut rt = Runtime::new().unwrap();
|
||||||
let work = TcpStream::connect(&addr, &core.handle());
|
let work = TcpStream::connect(&addr);
|
||||||
let host = addr.ip().to_string();
|
let host = addr.ip().to_string();
|
||||||
let port = addr.port();
|
let port = addr.port();
|
||||||
let work = work.and_then(|tcp| {
|
let work = work.and_then(|tcp| {
|
||||||
tunnel(tcp, host, port)
|
tunnel(tcp, host, port)
|
||||||
});
|
});
|
||||||
|
|
||||||
core.run(work).unwrap_err();
|
rt.block_on(work).unwrap_err();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_tunnel_bad_response() {
|
fn test_tunnel_bad_response() {
|
||||||
let addr = mock_tunnel!(b"foo bar baz hallo");
|
let addr = mock_tunnel!(b"foo bar baz hallo");
|
||||||
|
|
||||||
let mut core = Core::new().unwrap();
|
let mut rt = Runtime::new().unwrap();
|
||||||
let work = TcpStream::connect(&addr, &core.handle());
|
let work = TcpStream::connect(&addr);
|
||||||
let host = addr.ip().to_string();
|
let host = addr.ip().to_string();
|
||||||
let port = addr.port();
|
let port = addr.port();
|
||||||
let work = work.and_then(|tcp| {
|
let work = work.and_then(|tcp| {
|
||||||
tunnel(tcp, host, port)
|
tunnel(tcp, host, port)
|
||||||
});
|
});
|
||||||
|
|
||||||
core.run(work).unwrap_err();
|
rt.block_on(work).unwrap_err();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
36
src/error.rs
36
src/error.rs
@@ -112,6 +112,7 @@ impl Error {
|
|||||||
pub fn get_ref(&self) -> Option<&(StdError + Send + Sync + 'static)> {
|
pub fn get_ref(&self) -> Option<&(StdError + Send + Sync + 'static)> {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
Kind::Http(ref e) => Some(e),
|
Kind::Http(ref e) => Some(e),
|
||||||
|
Kind::Hyper(ref e) => Some(e),
|
||||||
Kind::Url(ref e) => Some(e),
|
Kind::Url(ref e) => Some(e),
|
||||||
Kind::Tls(ref e) => Some(e),
|
Kind::Tls(ref e) => Some(e),
|
||||||
Kind::Io(ref e) => Some(e),
|
Kind::Io(ref e) => Some(e),
|
||||||
@@ -129,6 +130,7 @@ impl Error {
|
|||||||
pub fn is_http(&self) -> bool {
|
pub fn is_http(&self) -> bool {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
Kind::Http(_) => true,
|
Kind::Http(_) => true,
|
||||||
|
Kind::Hyper(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,6 +192,7 @@ impl fmt::Display for Error {
|
|||||||
}
|
}
|
||||||
match self.kind {
|
match self.kind {
|
||||||
Kind::Http(ref e) => fmt::Display::fmt(e, f),
|
Kind::Http(ref e) => fmt::Display::fmt(e, f),
|
||||||
|
Kind::Hyper(ref e) => fmt::Display::fmt(e, f),
|
||||||
Kind::Url(ref e) => fmt::Display::fmt(e, f),
|
Kind::Url(ref e) => fmt::Display::fmt(e, f),
|
||||||
Kind::Tls(ref e) => fmt::Display::fmt(e, f),
|
Kind::Tls(ref e) => fmt::Display::fmt(e, f),
|
||||||
Kind::Io(ref e) => fmt::Display::fmt(e, f),
|
Kind::Io(ref e) => fmt::Display::fmt(e, f),
|
||||||
@@ -213,6 +216,7 @@ impl StdError for Error {
|
|||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
Kind::Http(ref e) => e.description(),
|
Kind::Http(ref e) => e.description(),
|
||||||
|
Kind::Hyper(ref e) => e.description(),
|
||||||
Kind::Url(ref e) => e.description(),
|
Kind::Url(ref e) => e.description(),
|
||||||
Kind::Tls(ref e) => e.description(),
|
Kind::Tls(ref e) => e.description(),
|
||||||
Kind::Io(ref e) => e.description(),
|
Kind::Io(ref e) => e.description(),
|
||||||
@@ -228,6 +232,7 @@ impl StdError for Error {
|
|||||||
fn cause(&self) -> Option<&StdError> {
|
fn cause(&self) -> Option<&StdError> {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
Kind::Http(ref e) => e.cause(),
|
Kind::Http(ref e) => e.cause(),
|
||||||
|
Kind::Hyper(ref e) => e.cause(),
|
||||||
Kind::Url(ref e) => e.cause(),
|
Kind::Url(ref e) => e.cause(),
|
||||||
Kind::Tls(ref e) => e.cause(),
|
Kind::Tls(ref e) => e.cause(),
|
||||||
Kind::Io(ref e) => e.cause(),
|
Kind::Io(ref e) => e.cause(),
|
||||||
@@ -245,7 +250,8 @@ impl StdError for Error {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Kind {
|
pub enum Kind {
|
||||||
Http(::hyper::Error),
|
Http(::http::Error),
|
||||||
|
Hyper(::hyper::Error),
|
||||||
Url(::url::ParseError),
|
Url(::url::ParseError),
|
||||||
Tls(::native_tls::Error),
|
Tls(::native_tls::Error),
|
||||||
Io(io::Error),
|
Io(io::Error),
|
||||||
@@ -258,13 +264,18 @@ pub enum Kind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl From<::http::Error> for Kind {
|
||||||
|
#[inline]
|
||||||
|
fn from(err: ::http::Error) -> Kind {
|
||||||
|
Kind::Http(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<::hyper::Error> for Kind {
|
impl From<::hyper::Error> for Kind {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(err: ::hyper::Error) -> Kind {
|
fn from(err: ::hyper::Error) -> Kind {
|
||||||
match err {
|
match err {
|
||||||
::hyper::Error::Io(err) => Kind::Io(err),
|
other => Kind::Hyper(other),
|
||||||
//::hyper::Error::Uri(err) => Kind::Url(err),
|
|
||||||
other => Kind::Http(other),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -430,20 +441,6 @@ pub fn server_error(url: Url, status: StatusCode) -> Error {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_error_get_ref_downcasts() {
|
|
||||||
let err: Error = from(::hyper::Error::Status);
|
|
||||||
let cause = err.get_ref()
|
|
||||||
.unwrap()
|
|
||||||
.downcast_ref::<::hyper::Error>()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
match cause {
|
|
||||||
&::hyper::Error::Status => (),
|
|
||||||
_ => panic!("unexpected downcast: {:?}", cause),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cause_chain() {
|
fn test_cause_chain() {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -476,9 +473,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let err = from(::hyper::Error::Status);
|
|
||||||
assert!(err.cause().is_none());
|
|
||||||
|
|
||||||
let root = Chain(None::<Error>);
|
let root = Chain(None::<Error>);
|
||||||
let io = ::std::io::Error::new(::std::io::ErrorKind::Other, root);
|
let io = ::std::io::Error::new(::std::io::ErrorKind::Other, root);
|
||||||
let err = Error { kind: Kind::Io(io), url: None };
|
let err = Error { kind: Kind::Io(io), url: None };
|
||||||
|
|||||||
@@ -36,7 +36,3 @@ impl<'a> PolyfillTryInto for &'a String {
|
|||||||
pub fn to_uri(url: &Url) -> ::hyper::Uri {
|
pub fn to_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 fn to_url(uri: &::hyper::Uri) -> Url {
|
|
||||||
uri.as_ref().parse().expect("reqwest Uris should only ever come from Urls")
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -124,15 +124,18 @@
|
|||||||
//! [serde]: http://serde.rs
|
//! [serde]: http://serde.rs
|
||||||
//! [cookiejar_issue]: https://github.com/seanmonstar/reqwest/issues/14
|
//! [cookiejar_issue]: https://github.com/seanmonstar/reqwest/issues/14
|
||||||
|
|
||||||
|
extern crate base64;
|
||||||
extern crate bytes;
|
extern crate bytes;
|
||||||
extern crate encoding_rs;
|
extern crate encoding_rs;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate futures;
|
extern crate futures;
|
||||||
|
extern crate http;
|
||||||
extern crate hyper;
|
extern crate hyper;
|
||||||
extern crate hyper_tls;
|
extern crate hyper_tls;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
extern crate libflate;
|
extern crate libflate;
|
||||||
|
extern crate mime;
|
||||||
extern crate mime_guess;
|
extern crate mime_guess;
|
||||||
extern crate native_tls;
|
extern crate native_tls;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
@@ -141,14 +144,13 @@ extern crate serde;
|
|||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate serde_urlencoded;
|
extern crate serde_urlencoded;
|
||||||
extern crate tokio_core;
|
extern crate tokio;
|
||||||
extern crate tokio_io;
|
extern crate tokio_io;
|
||||||
extern crate tokio_tls;
|
extern crate tokio_tls;
|
||||||
extern crate url;
|
extern crate url;
|
||||||
extern crate uuid;
|
extern crate uuid;
|
||||||
|
|
||||||
pub use hyper::header;
|
pub use hyper::header;
|
||||||
pub use hyper::mime;
|
|
||||||
pub use hyper::Method;
|
pub use hyper::Method;
|
||||||
pub use hyper::StatusCode;
|
pub use hyper::StatusCode;
|
||||||
pub use url::Url;
|
pub use url::Url;
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ use std::fs::File;
|
|||||||
use std::io::{self, Cursor, Read};
|
use std::io::{self, Cursor, Read};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use mime::Mime;
|
use mime_guess::{self, Mime};
|
||||||
use mime_guess;
|
|
||||||
use url::percent_encoding;
|
use url::percent_encoding;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
|||||||
128
src/proxy.rs
128
src/proxy.rs
@@ -1,7 +1,7 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hyper::Uri;
|
use hyper::client::connect::Destination;
|
||||||
use {into_url, IntoUrl, Url};
|
use {into_url, IntoUrl, Url};
|
||||||
|
|
||||||
/// Configuration of a proxy that a `Client` should pass requests to.
|
/// Configuration of a proxy that a `Client` should pass requests to.
|
||||||
@@ -128,36 +128,36 @@ impl Proxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn proxies(&self, url: &Url) -> bool {
|
fn intercept<D: Dst>(&self, uri: &D) -> Option<::hyper::Uri> {
|
||||||
match self.intercept {
|
|
||||||
Intercept::All(..) => true,
|
|
||||||
Intercept::Http(..) => url.scheme() == "http",
|
|
||||||
Intercept::Https(..) => url.scheme() == "https",
|
|
||||||
Intercept::Custom(ref fun) => (fun.0)(url).is_some(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn intercept(&self, uri: &Uri) -> Option<Uri> {
|
|
||||||
match self.intercept {
|
match self.intercept {
|
||||||
Intercept::All(ref u) => Some(u.clone()),
|
Intercept::All(ref u) => Some(u.clone()),
|
||||||
Intercept::Http(ref u) => {
|
Intercept::Http(ref u) => {
|
||||||
if uri.scheme() == Some("http") {
|
if uri.scheme() == "http" {
|
||||||
Some(u.clone())
|
Some(u.clone())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Intercept::Https(ref u) => {
|
Intercept::Https(ref u) => {
|
||||||
if uri.scheme() == Some("https") {
|
if uri.scheme() == "https" {
|
||||||
Some(u.clone())
|
Some(u.clone())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Intercept::Custom(ref fun) => {
|
Intercept::Custom(ref fun) => {
|
||||||
(fun.0)(&into_url::to_url(uri))
|
(fun.0)(
|
||||||
.map(|u| into_url::to_uri(&u))
|
&format!(
|
||||||
|
"{}://{}{}{}",
|
||||||
|
uri.scheme(),
|
||||||
|
uri.host(),
|
||||||
|
uri.port().map(|_| ":").unwrap_or(""),
|
||||||
|
uri.port().map(|p| p.to_string()).unwrap_or(String::new())
|
||||||
|
)
|
||||||
|
.parse()
|
||||||
|
.expect("should be valid Url")
|
||||||
|
)
|
||||||
|
.map(|u| into_url::to_uri(&u) )
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,9 +165,9 @@ impl Proxy {
|
|||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
enum Intercept {
|
enum Intercept {
|
||||||
All(Uri),
|
All(::hyper::Uri),
|
||||||
Http(Uri),
|
Http(::hyper::Uri),
|
||||||
Https(Uri),
|
Https(::hyper::Uri),
|
||||||
Custom(Custom),
|
Custom(Custom),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,20 +182,50 @@ impl fmt::Debug for Custom {
|
|||||||
|
|
||||||
// pub(crate)
|
// pub(crate)
|
||||||
|
|
||||||
pub fn intercept(proxy: &Proxy, uri: &Uri) -> Option<Uri> {
|
/// A helper trait to allow testing `Proxy::intercept` without having to
|
||||||
proxy.intercept(uri)
|
/// construct `hyper::client::connect::Destination`s.
|
||||||
|
trait Dst {
|
||||||
|
fn scheme(&self) -> &str;
|
||||||
|
fn host(&self) -> &str;
|
||||||
|
fn port(&self) -> Option<u16>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_proxied(proxies: &[Proxy], uri: &Url) -> bool {
|
#[doc(hidden)]
|
||||||
proxies.iter().any(|p| p.proxies(uri))
|
impl Dst for Destination {
|
||||||
|
fn scheme(&self) -> &str {
|
||||||
|
Destination::scheme(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn host(&self) -> &str {
|
||||||
|
Destination::host(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn port(&self) -> Option<u16> {
|
||||||
|
Destination::port(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn intercept(proxy: &Proxy, uri: &Destination) -> Option<::http::Uri> {
|
||||||
|
proxy.intercept(uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn uri(s: &str) -> Uri {
|
impl Dst for Url {
|
||||||
s.parse().unwrap()
|
fn scheme(&self) -> &str {
|
||||||
|
Url::scheme(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn host(&self) -> &str {
|
||||||
|
Url::host_str(self)
|
||||||
|
.expect("<Url as Dst>::host should have a str")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn port(&self) -> Option<u16> {
|
||||||
|
Url::port(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn url(s: &str) -> Url {
|
fn url(s: &str) -> Url {
|
||||||
@@ -210,10 +240,8 @@ mod tests {
|
|||||||
let http = "http://hyper.rs";
|
let http = "http://hyper.rs";
|
||||||
let other = "https://hyper.rs";
|
let other = "https://hyper.rs";
|
||||||
|
|
||||||
assert!(p.proxies(&url(http)));
|
assert_eq!(p.intercept(&url(http)).unwrap(), target);
|
||||||
assert_eq!(p.intercept(&uri(http)).unwrap(), target);
|
assert!(p.intercept(&url(other)).is_none());
|
||||||
assert!(!p.proxies(&url(other)));
|
|
||||||
assert!(p.intercept(&uri(other)).is_none());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -224,10 +252,8 @@ mod tests {
|
|||||||
let http = "http://hyper.rs";
|
let http = "http://hyper.rs";
|
||||||
let other = "https://hyper.rs";
|
let other = "https://hyper.rs";
|
||||||
|
|
||||||
assert!(!p.proxies(&url(http)));
|
assert!(p.intercept(&url(http)).is_none());
|
||||||
assert!(p.intercept(&uri(http)).is_none());
|
assert_eq!(p.intercept(&url(other)).unwrap(), target);
|
||||||
assert!(p.proxies(&url(other)));
|
|
||||||
assert_eq!(p.intercept(&uri(other)).unwrap(), target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -239,13 +265,9 @@ mod tests {
|
|||||||
let https = "https://hyper.rs";
|
let https = "https://hyper.rs";
|
||||||
let other = "x-youve-never-heard-of-me-mr-proxy://hyper.rs";
|
let other = "x-youve-never-heard-of-me-mr-proxy://hyper.rs";
|
||||||
|
|
||||||
assert!(p.proxies(&url(http)));
|
assert_eq!(p.intercept(&url(http)).unwrap(), target);
|
||||||
assert!(p.proxies(&url(https)));
|
assert_eq!(p.intercept(&url(https)).unwrap(), target);
|
||||||
assert!(p.proxies(&url(other)));
|
assert_eq!(p.intercept(&url(other)).unwrap(), target);
|
||||||
|
|
||||||
assert_eq!(p.intercept(&uri(http)).unwrap(), target);
|
|
||||||
assert_eq!(p.intercept(&uri(https)).unwrap(), target);
|
|
||||||
assert_eq!(p.intercept(&uri(other)).unwrap(), target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -267,29 +289,9 @@ mod tests {
|
|||||||
let https = "https://hyper.rs";
|
let https = "https://hyper.rs";
|
||||||
let other = "x-youve-never-heard-of-me-mr-proxy://seanmonstar.com";
|
let other = "x-youve-never-heard-of-me-mr-proxy://seanmonstar.com";
|
||||||
|
|
||||||
assert!(p.proxies(&url(http)));
|
assert_eq!(p.intercept(&url(http)).unwrap(), target2);
|
||||||
assert!(p.proxies(&url(https)));
|
assert_eq!(p.intercept(&url(https)).unwrap(), target1);
|
||||||
assert!(!p.proxies(&url(other)));
|
assert!(p.intercept(&url(other)).is_none());
|
||||||
|
|
||||||
assert_eq!(p.intercept(&uri(http)).unwrap(), target2);
|
|
||||||
assert_eq!(p.intercept(&uri(https)).unwrap(), target1);
|
|
||||||
assert!(p.intercept(&uri(other)).is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_is_proxied() {
|
|
||||||
let proxies = vec![
|
|
||||||
Proxy::http("http://example.domain").unwrap(),
|
|
||||||
Proxy::https("http://other.domain").unwrap(),
|
|
||||||
];
|
|
||||||
|
|
||||||
let http = "http://hyper.rs".parse().unwrap();
|
|
||||||
let https = "https://hyper.rs".parse().unwrap();
|
|
||||||
let other = "x-other://hyper.rs".parse().unwrap();
|
|
||||||
|
|
||||||
assert!(is_proxied(&proxies, &http));
|
|
||||||
assert!(is_proxied(&proxies, &https));
|
|
||||||
assert!(!is_proxied(&proxies, &other));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use hyper::header::Headers;
|
use header::HeaderMap;
|
||||||
use hyper::StatusCode;
|
use hyper::StatusCode;
|
||||||
|
|
||||||
use Url;
|
use Url;
|
||||||
@@ -228,15 +228,15 @@ pub fn check_redirect(
|
|||||||
.inner
|
.inner
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_sensitive_headers(headers: &mut Headers, next: &Url, previous: &[Url]) {
|
pub fn remove_sensitive_headers(headers: &mut HeaderMap, next: &Url, previous: &[Url]) {
|
||||||
if let Some(previous) = previous.last() {
|
if let Some(previous) = previous.last() {
|
||||||
let cross_host = next.host_str() != previous.host_str() ||
|
let cross_host = next.host_str() != previous.host_str() ||
|
||||||
next.port_or_known_default() != previous.port_or_known_default();
|
next.port_or_known_default() != previous.port_or_known_default();
|
||||||
if cross_host {
|
if cross_host {
|
||||||
headers.remove_raw("authorization");
|
headers.remove("authorization");
|
||||||
headers.remove_raw("cookie");
|
headers.remove("cookie");
|
||||||
headers.remove_raw("cookie2");
|
headers.remove("cookie2");
|
||||||
headers.remove_raw("www-authenticate");
|
headers.remove("www-authenticate");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -268,14 +268,14 @@ fn test_redirect_policy_limit() {
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
check_redirect(&policy, StatusCode::Found, &next, &previous),
|
check_redirect(&policy, StatusCode::FOUND, &next, &previous),
|
||||||
Action::Follow
|
Action::Follow
|
||||||
);
|
);
|
||||||
|
|
||||||
previous.push(Url::parse("http://a.b.d/e/33").unwrap());
|
previous.push(Url::parse("http://a.b.d/e/33").unwrap());
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
check_redirect(&policy, StatusCode::Found, &next, &previous),
|
check_redirect(&policy, StatusCode::FOUND, &next, &previous),
|
||||||
Action::TooManyRedirects
|
Action::TooManyRedirects
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -292,27 +292,25 @@ fn test_redirect_policy_custom() {
|
|||||||
|
|
||||||
let next = Url::parse("http://bar/baz").unwrap();
|
let next = Url::parse("http://bar/baz").unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
check_redirect(&policy, StatusCode::Found, &next, &[]),
|
check_redirect(&policy, StatusCode::FOUND, &next, &[]),
|
||||||
Action::Follow
|
Action::Follow
|
||||||
);
|
);
|
||||||
|
|
||||||
let next = Url::parse("http://foo/baz").unwrap();
|
let next = Url::parse("http://foo/baz").unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
check_redirect(&policy, StatusCode::Found, &next, &[]),
|
check_redirect(&policy, StatusCode::FOUND, &next, &[]),
|
||||||
Action::Stop
|
Action::Stop
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_remove_sensitive_headers() {
|
fn test_remove_sensitive_headers() {
|
||||||
use hyper::header::{Accept, Authorization, Cookie};
|
use hyper::header::{ACCEPT, AUTHORIZATION, COOKIE, HeaderValue};
|
||||||
|
|
||||||
let mut headers = Headers::new();
|
let mut headers = HeaderMap::new();
|
||||||
headers.set(Accept::star());
|
headers.insert(ACCEPT, HeaderValue::from_static("*/*"));
|
||||||
headers.set(Authorization("let me in".to_owned()));
|
headers.insert(AUTHORIZATION, HeaderValue::from_static("let me in"));
|
||||||
let mut cookie = Cookie::new();
|
headers.insert(COOKIE, HeaderValue::from_static("foo=bar"));
|
||||||
cookie.set("foo", "bar");
|
|
||||||
headers.set(cookie);
|
|
||||||
|
|
||||||
let next = Url::parse("http://initial-domain.com/path").unwrap();
|
let next = Url::parse("http://initial-domain.com/path").unwrap();
|
||||||
let mut prev = vec![Url::parse("http://initial-domain.com/new_path").unwrap()];
|
let mut prev = vec![Url::parse("http://initial-domain.com/new_path").unwrap()];
|
||||||
@@ -322,8 +320,8 @@ fn test_remove_sensitive_headers() {
|
|||||||
assert_eq!(headers, filtered_headers);
|
assert_eq!(headers, filtered_headers);
|
||||||
|
|
||||||
prev.push(Url::parse("http://new-domain.com/path").unwrap());
|
prev.push(Url::parse("http://new-domain.com/path").unwrap());
|
||||||
filtered_headers.remove::<Authorization<String>>();
|
filtered_headers.remove(AUTHORIZATION);
|
||||||
filtered_headers.remove::<Cookie>();
|
filtered_headers.remove(COOKIE);
|
||||||
|
|
||||||
remove_sensitive_headers(&mut headers, &next, &prev);
|
remove_sensitive_headers(&mut headers, &next, &prev);
|
||||||
assert_eq!(headers, filtered_headers);
|
assert_eq!(headers, filtered_headers);
|
||||||
|
|||||||
104
src/request.rs
104
src/request.rs
@@ -1,12 +1,13 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use hyper::header::ContentType;
|
use base64::encode;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use serde_urlencoded;
|
use serde_urlencoded;
|
||||||
|
|
||||||
use body::{self, Body};
|
use body::{self, Body};
|
||||||
use header::Headers;
|
use header::{HeaderMap, HeaderName, HeaderValue, CONTENT_TYPE};
|
||||||
|
use http::HttpTryFrom;
|
||||||
use {async_impl, Client, Method, Url};
|
use {async_impl, Client, Method, Url};
|
||||||
|
|
||||||
/// A request which can be executed with `Client::execute()`.
|
/// A request which can be executed with `Client::execute()`.
|
||||||
@@ -58,13 +59,13 @@ impl Request {
|
|||||||
|
|
||||||
/// Get the headers.
|
/// Get the headers.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn headers(&self) -> &Headers {
|
pub fn headers(&self) -> &HeaderMap {
|
||||||
self.inner.headers()
|
self.inner.headers()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a mutable reference to the headers.
|
/// Get a mutable reference to the headers.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn headers_mut(&mut self) -> &mut Headers {
|
pub fn headers_mut(&mut self) -> &mut HeaderMap {
|
||||||
self.inner.headers_mut()
|
self.inner.headers_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,22 +86,31 @@ impl RequestBuilder {
|
|||||||
/// Add a `Header` to this Request.
|
/// Add a `Header` to this Request.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use reqwest::header::UserAgent;
|
/// use reqwest::header::USER_AGENT;
|
||||||
///
|
///
|
||||||
/// # fn run() -> Result<(), Box<::std::error::Error>> {
|
/// # fn run() -> Result<(), Box<::std::error::Error>> {
|
||||||
/// let client = reqwest::Client::new();
|
/// let client = reqwest::Client::new();
|
||||||
/// let res = client.get("https://www.rust-lang.org")
|
/// let res = client.get("https://www.rust-lang.org")
|
||||||
/// .header(UserAgent::new("foo"))
|
/// .header(USER_AGENT, "foo")
|
||||||
/// .send()?;
|
/// .send()?;
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn header<H>(&mut self, header: H) -> &mut RequestBuilder
|
pub fn header<K, V>(&mut self, key: K, value: V) -> &mut RequestBuilder
|
||||||
where
|
where
|
||||||
H: ::header::Header,
|
HeaderName: HttpTryFrom<K>,
|
||||||
|
HeaderValue: HttpTryFrom<V>,
|
||||||
{
|
{
|
||||||
if let Some(req) = request_mut(&mut self.request, &self.err) {
|
if let Some(req) = request_mut(&mut self.request, &self.err) {
|
||||||
req.headers_mut().set(header);
|
match <HeaderName as HttpTryFrom<K>>::try_from(key) {
|
||||||
|
Ok(key) => {
|
||||||
|
match <HeaderValue as HttpTryFrom<V>>::try_from(value) {
|
||||||
|
Ok(value) => { req.headers_mut().append(key, value); }
|
||||||
|
Err(e) => self.err = Some(::error::from(e.into())),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => self.err = Some(::error::from(e.into())),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@@ -110,13 +120,13 @@ impl RequestBuilder {
|
|||||||
/// The headers will be merged in to any already set.
|
/// The headers will be merged in to any already set.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use reqwest::header::{Headers, UserAgent, ContentType};
|
/// use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT, CONTENT_TYPE};
|
||||||
/// # use std::fs;
|
/// # use std::fs;
|
||||||
///
|
///
|
||||||
/// fn construct_headers() -> Headers {
|
/// fn construct_headers() -> HeaderMap {
|
||||||
/// let mut headers = Headers::new();
|
/// let mut headers = HeaderMap::new();
|
||||||
/// headers.set(UserAgent::new("reqwest"));
|
/// headers.insert(USER_AGENT, HeaderValue::from_static("reqwest"));
|
||||||
/// headers.set(ContentType::png());
|
/// headers.insert(CONTENT_TYPE, HeaderValue::from_static("image/png"));
|
||||||
/// headers
|
/// headers
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
@@ -130,9 +140,11 @@ impl RequestBuilder {
|
|||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn headers(&mut self, headers: ::header::Headers) -> &mut RequestBuilder {
|
pub fn headers(&mut self, headers: ::header::HeaderMap) -> &mut RequestBuilder {
|
||||||
if let Some(req) = request_mut(&mut self.request, &self.err) {
|
if let Some(req) = request_mut(&mut self.request, &self.err) {
|
||||||
req.headers_mut().extend(headers.iter());
|
for (key, value) in headers.iter() {
|
||||||
|
req.headers_mut().insert(key, value.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@@ -153,10 +165,10 @@ impl RequestBuilder {
|
|||||||
U: Into<String>,
|
U: Into<String>,
|
||||||
P: Into<String>,
|
P: Into<String>,
|
||||||
{
|
{
|
||||||
self.header(::header::Authorization(::header::Basic {
|
let username = username.into();
|
||||||
username: username.into(),
|
let password = password.map(|p| p.into()).unwrap_or(String::new());
|
||||||
password: password.map(|p| p.into()),
|
let header_value = format!("basic {}:{}", username, encode(&password));
|
||||||
}))
|
self.header(::header::AUTHORIZATION, HeaderValue::from_str(header_value.as_str()).expect(""))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the request body.
|
/// Set the request body.
|
||||||
@@ -283,7 +295,7 @@ impl RequestBuilder {
|
|||||||
if let Some(req) = request_mut(&mut self.request, &self.err) {
|
if let Some(req) = request_mut(&mut self.request, &self.err) {
|
||||||
match serde_urlencoded::to_string(form) {
|
match serde_urlencoded::to_string(form) {
|
||||||
Ok(body) => {
|
Ok(body) => {
|
||||||
req.headers_mut().set(ContentType::form_url_encoded());
|
req.headers_mut().insert(CONTENT_TYPE, HeaderValue::from_str(::mime::APPLICATION_WWW_FORM_URLENCODED.as_ref()).expect(""));
|
||||||
*req.body_mut() = Some(body.into());
|
*req.body_mut() = Some(body.into());
|
||||||
},
|
},
|
||||||
Err(err) => self.err = Some(::error::from(err)),
|
Err(err) => self.err = Some(::error::from(err)),
|
||||||
@@ -321,7 +333,7 @@ impl RequestBuilder {
|
|||||||
if let Some(req) = request_mut(&mut self.request, &self.err) {
|
if let Some(req) = request_mut(&mut self.request, &self.err) {
|
||||||
match serde_json::to_vec(json) {
|
match serde_json::to_vec(json) {
|
||||||
Ok(body) => {
|
Ok(body) => {
|
||||||
req.headers_mut().set(ContentType::json());
|
req.headers_mut().insert(CONTENT_TYPE, HeaderValue::from_str(::mime::APPLICATION_JSON.as_ref()).expect(""));
|
||||||
*req.body_mut() = Some(body.into());
|
*req.body_mut() = Some(body.into());
|
||||||
},
|
},
|
||||||
Err(err) => self.err = Some(::error::from(err)),
|
Err(err) => self.err = Some(::error::from(err)),
|
||||||
@@ -333,7 +345,6 @@ impl RequestBuilder {
|
|||||||
/// Sends a multipart/form-data body.
|
/// Sends a multipart/form-data body.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use reqwest::mime;
|
|
||||||
/// # use reqwest::Error;
|
/// # use reqwest::Error;
|
||||||
///
|
///
|
||||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||||
@@ -352,10 +363,14 @@ impl RequestBuilder {
|
|||||||
/// See [`multipart`](multipart/) for more examples.
|
/// See [`multipart`](multipart/) for more examples.
|
||||||
pub fn multipart(&mut self, mut multipart: ::multipart::Form) -> &mut RequestBuilder {
|
pub fn multipart(&mut self, mut multipart: ::multipart::Form) -> &mut RequestBuilder {
|
||||||
if let Some(req) = request_mut(&mut self.request, &self.err) {
|
if let Some(req) = request_mut(&mut self.request, &self.err) {
|
||||||
req.headers_mut().set(
|
req.headers_mut().insert(
|
||||||
::header::ContentType(format!("multipart/form-data; boundary={}", ::multipart_::boundary(&multipart))
|
::header::CONTENT_TYPE,
|
||||||
.parse().unwrap()
|
HeaderValue::from_str(
|
||||||
)
|
format!(
|
||||||
|
"multipart/form-data; boundary={}",
|
||||||
|
::multipart_::boundary(&multipart)
|
||||||
|
).as_str()
|
||||||
|
).expect("")
|
||||||
);
|
);
|
||||||
*req.body_mut() = Some(match ::multipart_::compute_length(&mut multipart) {
|
*req.body_mut() = Some(match ::multipart_::compute_length(&mut multipart) {
|
||||||
Some(length) => Body::sized(::multipart_::reader(multipart), length),
|
Some(length) => Body::sized(::multipart_::reader(multipart), length),
|
||||||
@@ -450,13 +465,13 @@ pub fn builder(client: Client, req: ::Result<Request>) -> RequestBuilder {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn async(req: Request) -> (async_impl::Request, Option<body::Sender>) {
|
pub fn async(req: Request) -> (async_impl::Request, Option<body::Sender>) {
|
||||||
use header::ContentLength;
|
use header::CONTENT_LENGTH;
|
||||||
|
|
||||||
let mut req_async = req.inner;
|
let mut req_async = req.inner;
|
||||||
let body = req.body.and_then(|body| {
|
let body = req.body.and_then(|body| {
|
||||||
let (tx, body, len) = body::async(body);
|
let (tx, body, len) = body::async(body);
|
||||||
if let Some(len) = len {
|
if let Some(len) = len {
|
||||||
req_async.headers_mut().set(ContentLength(len));
|
req_async.headers_mut().insert(CONTENT_LENGTH, HeaderValue::from_str(len.to_string().as_str()).expect(""));
|
||||||
}
|
}
|
||||||
*req_async.body_mut() = Some(body);
|
*req_async.body_mut() = Some(body);
|
||||||
tx
|
tx
|
||||||
@@ -467,7 +482,7 @@ pub fn async(req: Request) -> (async_impl::Request, Option<body::Sender>) {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use {body, Client, Method};
|
use {body, Client, Method};
|
||||||
use header::{Host, Headers, ContentType};
|
use header::{HOST, HeaderMap, HeaderValue, CONTENT_TYPE};
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::{BTreeMap, HashMap};
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use serde_urlencoded;
|
use serde_urlencoded;
|
||||||
@@ -478,7 +493,7 @@ mod tests {
|
|||||||
let some_url = "https://google.com/";
|
let some_url = "https://google.com/";
|
||||||
let r = client.get(some_url).build().unwrap();
|
let r = client.get(some_url).build().unwrap();
|
||||||
|
|
||||||
assert_eq!(r.method(), &Method::Get);
|
assert_eq!(r.method(), &Method::GET);
|
||||||
assert_eq!(r.url().as_str(), some_url);
|
assert_eq!(r.url().as_str(), some_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,7 +503,7 @@ mod tests {
|
|||||||
let some_url = "https://google.com/";
|
let some_url = "https://google.com/";
|
||||||
let r = client.head(some_url).build().unwrap();
|
let r = client.head(some_url).build().unwrap();
|
||||||
|
|
||||||
assert_eq!(r.method(), &Method::Head);
|
assert_eq!(r.method(), &Method::HEAD);
|
||||||
assert_eq!(r.url().as_str(), some_url);
|
assert_eq!(r.url().as_str(), some_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,7 +513,7 @@ mod tests {
|
|||||||
let some_url = "https://google.com/";
|
let some_url = "https://google.com/";
|
||||||
let r = client.post(some_url).build().unwrap();
|
let r = client.post(some_url).build().unwrap();
|
||||||
|
|
||||||
assert_eq!(r.method(), &Method::Post);
|
assert_eq!(r.method(), &Method::POST);
|
||||||
assert_eq!(r.url().as_str(), some_url);
|
assert_eq!(r.url().as_str(), some_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,7 +523,7 @@ mod tests {
|
|||||||
let some_url = "https://google.com/";
|
let some_url = "https://google.com/";
|
||||||
let r = client.put(some_url).build().unwrap();
|
let r = client.put(some_url).build().unwrap();
|
||||||
|
|
||||||
assert_eq!(r.method(), &Method::Put);
|
assert_eq!(r.method(), &Method::PUT);
|
||||||
assert_eq!(r.url().as_str(), some_url);
|
assert_eq!(r.url().as_str(), some_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,7 +533,7 @@ mod tests {
|
|||||||
let some_url = "https://google.com/";
|
let some_url = "https://google.com/";
|
||||||
let r = client.patch(some_url).build().unwrap();
|
let r = client.patch(some_url).build().unwrap();
|
||||||
|
|
||||||
assert_eq!(r.method(), &Method::Patch);
|
assert_eq!(r.method(), &Method::PATCH);
|
||||||
assert_eq!(r.url().as_str(), some_url);
|
assert_eq!(r.url().as_str(), some_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -528,7 +543,7 @@ mod tests {
|
|||||||
let some_url = "https://google.com/";
|
let some_url = "https://google.com/";
|
||||||
let r = client.delete(some_url).build().unwrap();
|
let r = client.delete(some_url).build().unwrap();
|
||||||
|
|
||||||
assert_eq!(r.method(), &Method::Delete);
|
assert_eq!(r.method(), &Method::DELETE);
|
||||||
assert_eq!(r.url().as_str(), some_url);
|
assert_eq!(r.url().as_str(), some_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -538,13 +553,13 @@ mod tests {
|
|||||||
let some_url = "https://google.com/";
|
let some_url = "https://google.com/";
|
||||||
let mut r = client.post(some_url);
|
let mut r = client.post(some_url);
|
||||||
|
|
||||||
let header = Host::new("google.com", None);
|
let header = HeaderValue::from_static("google.com");
|
||||||
|
|
||||||
// Add a copy of the header to the request builder
|
// Add a copy of the header to the request builder
|
||||||
let r = r.header(header.clone()).build().unwrap();
|
let r = r.header(HOST, header.clone()).build().unwrap();
|
||||||
|
|
||||||
// then check it was actually added
|
// then check it was actually added
|
||||||
assert_eq!(r.headers().get::<Host>(), Some(&header));
|
assert_eq!(r.headers().get(HOST), Some(&header));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -553,10 +568,10 @@ mod tests {
|
|||||||
let some_url = "https://google.com/";
|
let some_url = "https://google.com/";
|
||||||
let mut r = client.post(some_url);
|
let mut r = client.post(some_url);
|
||||||
|
|
||||||
let header = Host::new("google.com", None);
|
let header = HeaderValue::from_static("google.com");
|
||||||
|
|
||||||
let mut headers = Headers::new();
|
let mut headers = HeaderMap::new();
|
||||||
headers.set(header);
|
headers.insert(HOST, header);
|
||||||
|
|
||||||
// Add a copy of the headers to the request builder
|
// Add a copy of the headers to the request builder
|
||||||
let r = r.headers(headers.clone()).build().unwrap();
|
let r = r.headers(headers.clone()).build().unwrap();
|
||||||
@@ -653,8 +668,7 @@ mod tests {
|
|||||||
let mut r = r.form(&form_data).build().unwrap();
|
let mut r = r.form(&form_data).build().unwrap();
|
||||||
|
|
||||||
// Make sure the content type was set
|
// Make sure the content type was set
|
||||||
assert_eq!(r.headers().get::<ContentType>(),
|
assert_eq!(r.headers().get(CONTENT_TYPE).unwrap(), &"application/x-www-form-urlencoded");
|
||||||
Some(&ContentType::form_url_encoded()));
|
|
||||||
|
|
||||||
let buf = body::read_to_string(r.body_mut().take().unwrap()).unwrap();
|
let buf = body::read_to_string(r.body_mut().take().unwrap()).unwrap();
|
||||||
|
|
||||||
@@ -674,7 +688,7 @@ mod tests {
|
|||||||
let mut r = r.json(&json_data).build().unwrap();
|
let mut r = r.json(&json_data).build().unwrap();
|
||||||
|
|
||||||
// Make sure the content type was set
|
// Make sure the content type was set
|
||||||
assert_eq!(r.headers().get::<ContentType>(), Some(&ContentType::json()));
|
assert_eq!(r.headers().get(CONTENT_TYPE).unwrap(), &"application/json");
|
||||||
|
|
||||||
let buf = body::read_to_string(r.body_mut().take().unwrap()).unwrap();
|
let buf = body::read_to_string(r.body_mut().take().unwrap()).unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -6,17 +6,19 @@ use std::borrow::Cow;
|
|||||||
|
|
||||||
use encoding_rs::{Encoding, UTF_8};
|
use encoding_rs::{Encoding, UTF_8};
|
||||||
use futures::{Async, Poll, Stream};
|
use futures::{Async, Poll, Stream};
|
||||||
|
use mime::Mime;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
|
||||||
use client::KeepCoreThreadAlive;
|
use client::KeepCoreThreadAlive;
|
||||||
use header::Headers;
|
use hyper::header::HeaderMap;
|
||||||
use {async_impl, StatusCode, Url, wait};
|
use {async_impl, StatusCode, Url, wait};
|
||||||
|
|
||||||
/// A Response to a submitted `Request`.
|
/// A Response to a submitted `Request`.
|
||||||
pub struct Response {
|
pub struct Response {
|
||||||
inner: async_impl::Response,
|
inner: async_impl::Response,
|
||||||
body: async_impl::ReadableChunks<WaitBody>,
|
body: async_impl::ReadableChunks<WaitBody>,
|
||||||
|
content_length: Option<u64>,
|
||||||
_thread_handle: KeepCoreThreadAlive,
|
_thread_handle: KeepCoreThreadAlive,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,8 +72,8 @@ impl Response {
|
|||||||
/// .body("possibly too large")
|
/// .body("possibly too large")
|
||||||
/// .send()?;
|
/// .send()?;
|
||||||
/// match resp.status() {
|
/// match resp.status() {
|
||||||
/// StatusCode::Ok => println!("success!"),
|
/// StatusCode::OK => println!("success!"),
|
||||||
/// StatusCode::PayloadTooLarge => {
|
/// StatusCode::PAYLOAD_TOO_LARGE => {
|
||||||
/// println!("Request payload is too large!");
|
/// println!("Request payload is too large!");
|
||||||
/// }
|
/// }
|
||||||
/// s => println!("Received response status: {:?}", s),
|
/// s => println!("Received response status: {:?}", s),
|
||||||
@@ -93,14 +95,15 @@ impl Response {
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use std::io::{Read, Write};
|
/// # use std::io::{Read, Write};
|
||||||
/// # use reqwest::Client;
|
/// # use reqwest::Client;
|
||||||
/// # use reqwest::header::ContentLength;
|
/// # use reqwest::header::CONTENT_LENGTH;
|
||||||
/// #
|
/// #
|
||||||
/// # fn run() -> Result<(), Box<::std::error::Error>> {
|
/// # fn run() -> Result<(), Box<::std::error::Error>> {
|
||||||
/// let client = Client::new();
|
/// let client = Client::new();
|
||||||
/// let mut resp = client.head("http://httpbin.org/bytes/3000").send()?;
|
/// let mut resp = client.head("http://httpbin.org/bytes/3000").send()?;
|
||||||
/// if resp.status().is_success() {
|
/// if resp.status().is_success() {
|
||||||
/// let len = resp.headers().get::<ContentLength>()
|
/// let len = resp.headers().get(CONTENT_LENGTH)
|
||||||
/// .map(|ct_len| **ct_len)
|
/// .and_then(|ct_len| ct_len.to_str().ok())
|
||||||
|
/// .and_then(|ct_len| ct_len.parse().ok())
|
||||||
/// .unwrap_or(0);
|
/// .unwrap_or(0);
|
||||||
/// // limit 1mb response
|
/// // limit 1mb response
|
||||||
/// if len <= 1_000_000 {
|
/// if len <= 1_000_000 {
|
||||||
@@ -115,7 +118,7 @@ impl Response {
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn headers(&self) -> &Headers {
|
pub fn headers(&self) -> &HeaderMap {
|
||||||
self.inner.headers()
|
self.inner.headers()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,14 +192,21 @@ impl Response {
|
|||||||
/// This consumes the body. Trying to read more, or use of `response.json()`
|
/// This consumes the body. Trying to read more, or use of `response.json()`
|
||||||
/// will return empty values.
|
/// will return empty values.
|
||||||
pub fn text(&mut self) -> ::Result<String> {
|
pub fn text(&mut self) -> ::Result<String> {
|
||||||
let len = self.headers().get::<::header::ContentLength>()
|
let len = self.content_length.unwrap_or(0);
|
||||||
.map(|ct_len| **ct_len)
|
|
||||||
.unwrap_or(0);
|
|
||||||
let mut content = Vec::with_capacity(len as usize);
|
let mut content = Vec::with_capacity(len as usize);
|
||||||
self.read_to_end(&mut content).map_err(::error::from)?;
|
self.read_to_end(&mut content).map_err(::error::from)?;
|
||||||
let encoding_name = self.headers().get::<::header::ContentType>()
|
let content_type = self.headers().get(::header::CONTENT_TYPE)
|
||||||
.and_then(|content_type| {
|
.and_then(|value| {
|
||||||
content_type.get_param("charset")
|
value.to_str().ok()
|
||||||
|
})
|
||||||
|
.and_then(|value| {
|
||||||
|
value.parse::<Mime>().ok()
|
||||||
|
});
|
||||||
|
let encoding_name = content_type
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|mime| {
|
||||||
|
mime
|
||||||
|
.get_param("charset")
|
||||||
.map(|charset| charset.as_str())
|
.map(|charset| charset.as_str())
|
||||||
})
|
})
|
||||||
.unwrap_or("utf-8");
|
.unwrap_or("utf-8");
|
||||||
@@ -252,7 +262,7 @@ impl Response {
|
|||||||
/// let res = reqwest::get("http://httpbin.org/status/400")?
|
/// let res = reqwest::get("http://httpbin.org/status/400")?
|
||||||
/// .error_for_status();
|
/// .error_for_status();
|
||||||
/// if let Err(err) = res {
|
/// if let Err(err) = res {
|
||||||
/// assert_eq!(err.status(), Some(reqwest::StatusCode::BadRequest));
|
/// assert_eq!(err.status(), Some(reqwest::StatusCode::BAD_REQUEST));
|
||||||
/// }
|
/// }
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
@@ -260,12 +270,13 @@ impl Response {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn error_for_status(self) -> ::Result<Self> {
|
pub fn error_for_status(self) -> ::Result<Self> {
|
||||||
let Response { body, inner, _thread_handle } = self;
|
let Response { body, content_length, inner, _thread_handle } = self;
|
||||||
inner.error_for_status().map(move |inner| {
|
inner.error_for_status().map(move |inner| {
|
||||||
Response {
|
Response {
|
||||||
inner: inner,
|
inner,
|
||||||
body: body,
|
body,
|
||||||
_thread_handle: _thread_handle,
|
content_length,
|
||||||
|
_thread_handle,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -306,6 +317,7 @@ impl Stream for WaitBody {
|
|||||||
|
|
||||||
pub fn new(mut res: async_impl::Response, timeout: Option<Duration>, thread: KeepCoreThreadAlive) -> Response {
|
pub fn new(mut res: async_impl::Response, timeout: Option<Duration>, thread: KeepCoreThreadAlive) -> Response {
|
||||||
let body = mem::replace(res.body_mut(), async_impl::Decoder::empty());
|
let body = mem::replace(res.body_mut(), async_impl::Decoder::empty());
|
||||||
|
let len = body.content_length();
|
||||||
let body = async_impl::ReadableChunks::new(WaitBody {
|
let body = async_impl::ReadableChunks::new(WaitBody {
|
||||||
inner: wait::stream(body, timeout)
|
inner: wait::stream(body, timeout)
|
||||||
});
|
});
|
||||||
@@ -313,6 +325,7 @@ pub fn new(mut res: async_impl::Response, timeout: Option<Duration>, thread: Kee
|
|||||||
Response {
|
Response {
|
||||||
inner: res,
|
inner: res,
|
||||||
body: body,
|
body: body,
|
||||||
|
content_length: len,
|
||||||
_thread_handle: thread,
|
_thread_handle: thread,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
53
src/wait.rs
53
src/wait.rs
@@ -2,7 +2,7 @@ use std::sync::Arc;
|
|||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use futures::{Async, AsyncSink, Future, Sink, Stream};
|
use futures::{Async, Future, Stream};
|
||||||
use futures::executor::{self, Notify};
|
use futures::executor::{self, Notify};
|
||||||
|
|
||||||
// pub(crate)
|
// pub(crate)
|
||||||
@@ -43,14 +43,6 @@ where S: Stream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sink<S>(sink: S, timeout: Option<Duration>) -> WaitSink<S>
|
|
||||||
where S: Sink {
|
|
||||||
WaitSink {
|
|
||||||
sink: executor::spawn(sink),
|
|
||||||
timeout: timeout,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Waited<E> {
|
pub enum Waited<E> {
|
||||||
TimedOut,
|
TimedOut,
|
||||||
@@ -113,49 +105,6 @@ where S: Stream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WaitSink<S> {
|
|
||||||
sink: executor::Spawn<S>,
|
|
||||||
timeout: Option<Duration>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> WaitSink<S>
|
|
||||||
where S: Sink {
|
|
||||||
pub fn send(&mut self, mut item: S::SinkItem) -> Result<(), Waited<S::SinkError>> {
|
|
||||||
if let Some(dur) = self.timeout {
|
|
||||||
|
|
||||||
let start = Instant::now();
|
|
||||||
let deadline = start + dur;
|
|
||||||
let notify = Arc::new(ThreadNotify {
|
|
||||||
thread: thread::current(),
|
|
||||||
});
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let now = Instant::now();
|
|
||||||
if now >= deadline {
|
|
||||||
return Err(Waited::TimedOut);
|
|
||||||
}
|
|
||||||
item = match self.sink.start_send_notify(item, ¬ify, 0)? {
|
|
||||||
AsyncSink::Ready => return Ok(()),
|
|
||||||
AsyncSink::NotReady(val) => val,
|
|
||||||
};
|
|
||||||
thread::park_timeout(deadline - now);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let notify = Arc::new(ThreadNotify {
|
|
||||||
thread: thread::current(),
|
|
||||||
});
|
|
||||||
|
|
||||||
loop {
|
|
||||||
item = match self.sink.start_send_notify(item, ¬ify, 0)? {
|
|
||||||
AsyncSink::Ready => return Ok(()),
|
|
||||||
AsyncSink::NotReady(val) => val,
|
|
||||||
};
|
|
||||||
thread::park();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ThreadNotify {
|
struct ThreadNotify {
|
||||||
thread: thread::Thread,
|
thread: thread::Thread,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
#![cfg(feature="unstable")]
|
#![cfg(feature="unstable")]
|
||||||
|
|
||||||
extern crate futures;
|
extern crate futures;
|
||||||
extern crate tokio_core;
|
|
||||||
extern crate reqwest;
|
|
||||||
extern crate libflate;
|
extern crate libflate;
|
||||||
|
extern crate reqwest;
|
||||||
|
extern crate tokio;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod support;
|
mod support;
|
||||||
|
|
||||||
use reqwest::unstable::async::Client;
|
use reqwest::unstable::async::Client;
|
||||||
use futures::{Future, Stream};
|
use futures::{Future, Stream};
|
||||||
use tokio_core::reactor::Core;
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@@ -46,10 +45,10 @@ fn test_gzip(response_size: usize, chunk_size: usize) {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /gzip HTTP/1.1\r\n\
|
GET /gzip HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
chunk_size: chunk_size,
|
chunk_size: chunk_size,
|
||||||
@@ -57,9 +56,9 @@ fn test_gzip(response_size: usize, chunk_size: usize) {
|
|||||||
response: response
|
response: response
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut core = Core::new().unwrap();
|
let mut rt = tokio::runtime::current_thread::Runtime::new().expect("new rt");
|
||||||
|
|
||||||
let client = Client::new(&core.handle());
|
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()
|
.send()
|
||||||
@@ -75,5 +74,5 @@ fn test_gzip(response_size: usize, chunk_size: usize) {
|
|||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|
||||||
core.run(res_future).unwrap();
|
rt.block_on(res_future).unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
169
tests/client.rs
169
tests/client.rs
@@ -10,10 +10,10 @@ fn test_response_text() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /text HTTP/1.1\r\n\
|
GET /text HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -28,11 +28,9 @@ fn test_response_text() {
|
|||||||
let url = format!("http://{}/text", server.addr());
|
let url = format!("http://{}/text", server.addr());
|
||||||
let mut res = reqwest::get(&url).unwrap();
|
let mut res = reqwest::get(&url).unwrap();
|
||||||
assert_eq!(res.url().as_str(), &url);
|
assert_eq!(res.url().as_str(), &url);
|
||||||
assert_eq!(res.status(), reqwest::StatusCode::Ok);
|
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||||
assert_eq!(res.headers().get(),
|
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||||
Some(&reqwest::header::Server::new("test".to_string())));
|
assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"5");
|
||||||
assert_eq!(res.headers().get(),
|
|
||||||
Some(&reqwest::header::ContentLength(5)));
|
|
||||||
|
|
||||||
let body = res.text().unwrap();
|
let body = res.text().unwrap();
|
||||||
assert_eq!(b"Hello", body.as_bytes());
|
assert_eq!(b"Hello", body.as_bytes());
|
||||||
@@ -43,10 +41,10 @@ fn test_response_non_utf_8_text() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /text HTTP/1.1\r\n\
|
GET /text HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -62,11 +60,9 @@ fn test_response_non_utf_8_text() {
|
|||||||
let url = format!("http://{}/text", server.addr());
|
let url = format!("http://{}/text", server.addr());
|
||||||
let mut res = reqwest::get(&url).unwrap();
|
let mut res = reqwest::get(&url).unwrap();
|
||||||
assert_eq!(res.url().as_str(), &url);
|
assert_eq!(res.url().as_str(), &url);
|
||||||
assert_eq!(res.status(), reqwest::StatusCode::Ok);
|
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||||
assert_eq!(res.headers().get(),
|
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||||
Some(&reqwest::header::Server::new("test".to_string())));
|
assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"4");
|
||||||
assert_eq!(res.headers().get(),
|
|
||||||
Some(&reqwest::header::ContentLength(4)));
|
|
||||||
|
|
||||||
let body = res.text().unwrap();
|
let body = res.text().unwrap();
|
||||||
assert_eq!("你好", &body);
|
assert_eq!("你好", &body);
|
||||||
@@ -78,10 +74,10 @@ fn test_response_copy_to() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /1 HTTP/1.1\r\n\
|
GET /1 HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -96,11 +92,9 @@ fn test_response_copy_to() {
|
|||||||
let url = format!("http://{}/1", server.addr());
|
let url = format!("http://{}/1", server.addr());
|
||||||
let mut res = reqwest::get(&url).unwrap();
|
let mut res = reqwest::get(&url).unwrap();
|
||||||
assert_eq!(res.url().as_str(), &url);
|
assert_eq!(res.url().as_str(), &url);
|
||||||
assert_eq!(res.status(), reqwest::StatusCode::Ok);
|
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||||
assert_eq!(res.headers().get(),
|
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||||
Some(&reqwest::header::Server::new("test".to_string())));
|
assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"5");
|
||||||
assert_eq!(res.headers().get(),
|
|
||||||
Some(&reqwest::header::ContentLength(5)));
|
|
||||||
|
|
||||||
let mut buf: Vec<u8> = vec![];
|
let mut buf: Vec<u8> = vec![];
|
||||||
res.copy_to(&mut buf).unwrap();
|
res.copy_to(&mut buf).unwrap();
|
||||||
@@ -112,10 +106,10 @@ fn test_get() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /1 HTTP/1.1\r\n\
|
GET /1 HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -130,11 +124,9 @@ fn test_get() {
|
|||||||
let mut res = reqwest::get(&url).unwrap();
|
let mut res = reqwest::get(&url).unwrap();
|
||||||
|
|
||||||
assert_eq!(res.url().as_str(), &url);
|
assert_eq!(res.url().as_str(), &url);
|
||||||
assert_eq!(res.status(), reqwest::StatusCode::Ok);
|
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||||
assert_eq!(res.headers().get(),
|
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||||
Some(&reqwest::header::Server::new("test".to_string())));
|
assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"0");
|
||||||
assert_eq!(res.headers().get(),
|
|
||||||
Some(&reqwest::header::ContentLength(0)));
|
|
||||||
|
|
||||||
let mut buf = [0; 1024];
|
let mut buf = [0; 1024];
|
||||||
let n = res.read(&mut buf).unwrap();
|
let n = res.read(&mut buf).unwrap();
|
||||||
@@ -146,11 +138,11 @@ fn test_post() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
POST /2 HTTP/1.1\r\n\
|
POST /2 HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
content-length: 5\r\n\
|
||||||
Content-Length: 5\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
Hello\
|
Hello\
|
||||||
",
|
",
|
||||||
@@ -170,11 +162,9 @@ fn test_post() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(res.url().as_str(), &url);
|
assert_eq!(res.url().as_str(), &url);
|
||||||
assert_eq!(res.status(), reqwest::StatusCode::Ok);
|
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||||
assert_eq!(res.headers().get(),
|
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"post");
|
||||||
Some(&reqwest::header::Server::new("post")));
|
assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"0");
|
||||||
assert_eq!(res.headers().get(),
|
|
||||||
Some(&reqwest::header::ContentLength(0)));
|
|
||||||
|
|
||||||
let mut buf = [0; 1024];
|
let mut buf = [0; 1024];
|
||||||
let n = res.read(&mut buf).unwrap();
|
let n = res.read(&mut buf).unwrap();
|
||||||
@@ -188,10 +178,10 @@ fn test_error_for_status_4xx() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /1 HTTP/1.1\r\n\
|
GET /1 HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -207,7 +197,7 @@ fn test_error_for_status_4xx() {
|
|||||||
|
|
||||||
let err = res.error_for_status().err().unwrap();
|
let err = res.error_for_status().err().unwrap();
|
||||||
assert!(err.is_client_error());
|
assert!(err.is_client_error());
|
||||||
assert_eq!(err.status(), Some(reqwest::StatusCode::BadRequest));
|
assert_eq!(err.status(), Some(reqwest::StatusCode::BAD_REQUEST));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calling `Response::error_for_status`` on a response with status in 5xx
|
/// Calling `Response::error_for_status`` on a response with status in 5xx
|
||||||
@@ -217,10 +207,10 @@ fn test_error_for_status_5xx() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /1 HTTP/1.1\r\n\
|
GET /1 HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -236,17 +226,14 @@ fn test_error_for_status_5xx() {
|
|||||||
|
|
||||||
let err = res.error_for_status().err().unwrap();
|
let err = res.error_for_status().err().unwrap();
|
||||||
assert!(err.is_server_error());
|
assert!(err.is_server_error());
|
||||||
assert_eq!(err.status(), Some(reqwest::StatusCode::InternalServerError));
|
assert_eq!(err.status(), Some(reqwest::StatusCode::INTERNAL_SERVER_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_default_headers() {
|
fn test_default_headers() {
|
||||||
use reqwest::header;
|
use reqwest::header;
|
||||||
let mut headers = header::Headers::with_capacity(1);
|
let mut headers = header::HeaderMap::with_capacity(1);
|
||||||
let mut cookies = header::Cookie::new();
|
headers.insert(header::COOKIE, header::HeaderValue::from_static("a=b;c=d"));
|
||||||
cookies.set("a", "b");
|
|
||||||
cookies.set("c", "d");
|
|
||||||
headers.set(cookies);
|
|
||||||
let client = reqwest::Client::builder()
|
let client = reqwest::Client::builder()
|
||||||
.default_headers(headers)
|
.default_headers(headers)
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
@@ -254,11 +241,11 @@ fn test_default_headers() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /1 HTTP/1.1\r\n\
|
GET /1 HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
cookie: a=b;c=d\r\n\
|
||||||
Cookie: a=b; c=d\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -273,20 +260,18 @@ fn test_default_headers() {
|
|||||||
let res = client.get(&url).send().unwrap();
|
let res = client.get(&url).send().unwrap();
|
||||||
|
|
||||||
assert_eq!(res.url().as_str(), &url);
|
assert_eq!(res.url().as_str(), &url);
|
||||||
assert_eq!(res.status(), reqwest::StatusCode::Ok);
|
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||||
assert_eq!(res.headers().get(),
|
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||||
Some(&reqwest::header::Server::new("test")));
|
assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"0");
|
||||||
assert_eq!(res.headers().get(),
|
|
||||||
Some(&reqwest::header::ContentLength(0)));
|
|
||||||
|
|
||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /2 HTTP/1.1\r\n\
|
GET /2 HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
cookie: a=b;c=d\r\n\
|
||||||
Cookie: a=b; c=d\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -301,18 +286,16 @@ fn test_default_headers() {
|
|||||||
let res = client.get(&url).send().unwrap();
|
let res = client.get(&url).send().unwrap();
|
||||||
|
|
||||||
assert_eq!(res.url().as_str(), &url);
|
assert_eq!(res.url().as_str(), &url);
|
||||||
assert_eq!(res.status(), reqwest::StatusCode::Ok);
|
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||||
assert_eq!(res.headers().get(),
|
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||||
Some(&reqwest::header::Server::new("test")));
|
assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"0");
|
||||||
assert_eq!(res.headers().get(),
|
|
||||||
Some(&reqwest::header::ContentLength(0)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_override_default_headers() {
|
fn test_override_default_headers() {
|
||||||
use reqwest::header;
|
use reqwest::header;
|
||||||
let mut headers = header::Headers::with_capacity(1);
|
let mut headers = header::HeaderMap::with_capacity(1);
|
||||||
headers.set(header::Authorization("iamatoken".to_string()));
|
headers.insert(header::AUTHORIZATION, header::HeaderValue::from_static("iamatoken"));
|
||||||
let client = reqwest::Client::builder()
|
let client = reqwest::Client::builder()
|
||||||
.default_headers(headers)
|
.default_headers(headers)
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
@@ -320,11 +303,11 @@ fn test_override_default_headers() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /3 HTTP/1.1\r\n\
|
GET /3 HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
authorization: secret\r\n\
|
||||||
Authorization: secret\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -336,13 +319,11 @@ fn test_override_default_headers() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let url = format!("http://{}/3", server.addr());
|
let url = format!("http://{}/3", server.addr());
|
||||||
let res = client.get(&url).header(header::Authorization("secret".to_string())).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.url().as_str(), &url);
|
||||||
assert_eq!(res.status(), reqwest::StatusCode::Ok);
|
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||||
assert_eq!(res.headers().get(),
|
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||||
Some(&reqwest::header::Server::new("test")));
|
assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"0");
|
||||||
assert_eq!(res.headers().get(),
|
|
||||||
Some(&reqwest::header::ContentLength(0)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ fn test_gzip_response() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /gzip HTTP/1.1\r\n\
|
GET /gzip HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
chunk_size: chunk_size,
|
chunk_size: chunk_size,
|
||||||
@@ -54,10 +54,10 @@ fn test_gzip_empty_body() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
HEAD /gzip HTTP/1.1\r\n\
|
HEAD /gzip HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -85,10 +85,10 @@ fn test_gzip_invalid_body() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /gzip HTTP/1.1\r\n\
|
GET /gzip HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -113,10 +113,10 @@ fn test_accept_header_is_not_changed_if_set() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /accept HTTP/1.1\r\n\
|
GET /accept HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: application/json\r\n\
|
||||||
Accept: application/json\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -130,11 +130,11 @@ fn test_accept_header_is_not_changed_if_set() {
|
|||||||
|
|
||||||
let res = client
|
let res = client
|
||||||
.get(&format!("http://{}/accept", server.addr()))
|
.get(&format!("http://{}/accept", server.addr()))
|
||||||
.header(reqwest::header::Accept::json())
|
.header(reqwest::header::ACCEPT, reqwest::header::HeaderValue::from_static("application/json"))
|
||||||
.send()
|
.send()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(res.status(), reqwest::StatusCode::Ok);
|
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -142,10 +142,10 @@ fn test_accept_encoding_header_is_not_changed_if_set() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /accept-encoding HTTP/1.1\r\n\
|
GET /accept-encoding HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: identity\r\n\
|
||||||
Accept-Encoding: identity\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -158,11 +158,9 @@ fn test_accept_encoding_header_is_not_changed_if_set() {
|
|||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
|
|
||||||
let res = client.get(&format!("http://{}/accept-encoding", server.addr()))
|
let res = client.get(&format!("http://{}/accept-encoding", server.addr()))
|
||||||
.header(reqwest::header::AcceptEncoding(
|
.header(reqwest::header::ACCEPT_ENCODING, reqwest::header::HeaderValue::from_static("identity"))
|
||||||
vec![reqwest::header::qitem(reqwest::header::Encoding::Identity)]
|
|
||||||
))
|
|
||||||
.send()
|
.send()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(res.status(), reqwest::StatusCode::Ok);
|
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ fn test_multipart() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: format!("\
|
request: format!("\
|
||||||
POST /multipart/1 HTTP/1.1\r\n\
|
POST /multipart/1 HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
content-type: multipart/form-data; boundary={}\r\n\
|
||||||
Content-Type: multipart/form-data; boundary={}\r\n\
|
content-length: 123\r\n\
|
||||||
Content-Length: 123\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
{}\
|
{}\
|
||||||
", form.boundary(), expected_body),
|
", form.boundary(), expected_body),
|
||||||
@@ -47,5 +47,5 @@ fn test_multipart() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(res.url().as_str(), &url);
|
assert_eq!(res.url().as_str(), &url);
|
||||||
assert_eq!(res.status(), reqwest::StatusCode::Ok);
|
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ fn test_http_proxy() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET http://hyper.rs/prox HTTP/1.1\r\n\
|
GET http://hyper.rs/prox HTTP/1.1\r\n\
|
||||||
Host: hyper.rs\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: hyper.rs\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -34,7 +34,6 @@ fn test_http_proxy() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(res.url().as_str(), url);
|
assert_eq!(res.url().as_str(), url);
|
||||||
assert_eq!(res.status(), reqwest::StatusCode::Ok);
|
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||||
assert_eq!(res.headers().get(),
|
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"proxied");
|
||||||
Some(&reqwest::header::Server::new("proxied")));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ fn test_redirect_301_and_302_and_303_changes_post_to_get() {
|
|||||||
let redirect = server! {
|
let redirect = server! {
|
||||||
request: format!("\
|
request: format!("\
|
||||||
POST /{} HTTP/1.1\r\n\
|
POST /{} HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
", code),
|
", code),
|
||||||
response: format!("\
|
response: format!("\
|
||||||
@@ -29,11 +29,11 @@ fn test_redirect_301_and_302_and_303_changes_post_to_get() {
|
|||||||
|
|
||||||
request: format!("\
|
request: format!("\
|
||||||
GET /dst HTTP/1.1\r\n\
|
GET /dst HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
referer: http://$HOST/{}\r\n\
|
||||||
Referer: http://$HOST/{}\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
", code),
|
", code),
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -50,9 +50,8 @@ fn test_redirect_301_and_302_and_303_changes_post_to_get() {
|
|||||||
.send()
|
.send()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(res.url().as_str(), dst);
|
assert_eq!(res.url().as_str(), dst);
|
||||||
assert_eq!(res.status(), reqwest::StatusCode::Ok);
|
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||||
assert_eq!(res.headers().get(),
|
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test-dst");
|
||||||
Some(&reqwest::header::Server::new("test-dst".to_string())));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,10 +63,10 @@ fn test_redirect_307_and_308_tries_to_get_again() {
|
|||||||
let redirect = server! {
|
let redirect = server! {
|
||||||
request: format!("\
|
request: format!("\
|
||||||
GET /{} HTTP/1.1\r\n\
|
GET /{} HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
", code),
|
", code),
|
||||||
response: format!("\
|
response: format!("\
|
||||||
@@ -81,11 +80,11 @@ fn test_redirect_307_and_308_tries_to_get_again() {
|
|||||||
|
|
||||||
request: format!("\
|
request: format!("\
|
||||||
GET /dst HTTP/1.1\r\n\
|
GET /dst HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
referer: http://$HOST/{}\r\n\
|
||||||
Referer: http://$HOST/{}\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
", code),
|
", code),
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -102,9 +101,8 @@ fn test_redirect_307_and_308_tries_to_get_again() {
|
|||||||
.send()
|
.send()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(res.url().as_str(), dst);
|
assert_eq!(res.url().as_str(), dst);
|
||||||
assert_eq!(res.status(), reqwest::StatusCode::Ok);
|
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||||
assert_eq!(res.headers().get(),
|
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test-dst");
|
||||||
Some(&reqwest::header::Server::new("test-dst".to_string())));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,11 +114,11 @@ fn test_redirect_307_and_308_tries_to_post_again() {
|
|||||||
let redirect = server! {
|
let redirect = server! {
|
||||||
request: format!("\
|
request: format!("\
|
||||||
POST /{} HTTP/1.1\r\n\
|
POST /{} HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
content-length: 5\r\n\
|
||||||
Content-Length: 5\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
Hello\
|
Hello\
|
||||||
", code),
|
", code),
|
||||||
@@ -135,12 +133,12 @@ fn test_redirect_307_and_308_tries_to_post_again() {
|
|||||||
|
|
||||||
request: format!("\
|
request: format!("\
|
||||||
POST /dst HTTP/1.1\r\n\
|
POST /dst HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
content-length: 5\r\n\
|
||||||
Content-Length: 5\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
referer: http://$HOST/{}\r\n\
|
||||||
Referer: http://$HOST/{}\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
Hello\
|
Hello\
|
||||||
", code),
|
", code),
|
||||||
@@ -159,9 +157,8 @@ fn test_redirect_307_and_308_tries_to_post_again() {
|
|||||||
.send()
|
.send()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(res.url().as_str(), dst);
|
assert_eq!(res.url().as_str(), dst);
|
||||||
assert_eq!(res.status(), reqwest::StatusCode::Ok);
|
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||||
assert_eq!(res.headers().get(),
|
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test-dst");
|
||||||
Some(&reqwest::header::Server::new("test-dst".to_string())));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,11 +170,11 @@ fn test_redirect_307_does_not_try_if_reader_cannot_reset() {
|
|||||||
let redirect = server! {
|
let redirect = server! {
|
||||||
request: format!("\
|
request: format!("\
|
||||||
POST /{} HTTP/1.1\r\n\
|
POST /{} HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
Transfer-Encoding: chunked\r\n\
|
transfer-encoding: chunked\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
5\r\n\
|
5\r\n\
|
||||||
Hello\r\n\
|
Hello\r\n\
|
||||||
@@ -200,7 +197,7 @@ fn test_redirect_307_does_not_try_if_reader_cannot_reset() {
|
|||||||
.send()
|
.send()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(res.url().as_str(), url);
|
assert_eq!(res.url().as_str(), url);
|
||||||
assert_eq!(res.status(), reqwest::StatusCode::try_from(code).unwrap());
|
assert_eq!(res.status(), reqwest::StatusCode::from_u16(code).unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,10 +208,10 @@ fn test_redirect_removes_sensitive_headers() {
|
|||||||
let end_server = server! {
|
let end_server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /otherhost HTTP/1.1\r\n\
|
GET /otherhost HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -228,11 +225,11 @@ fn test_redirect_removes_sensitive_headers() {
|
|||||||
let mid_server = server! {
|
let mid_server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /sensitive HTTP/1.1\r\n\
|
GET /sensitive HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
cookie: foo=bar\r\n\
|
||||||
Cookie: foo=bar\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: format!("\
|
response: format!("\
|
||||||
@@ -244,14 +241,12 @@ fn test_redirect_removes_sensitive_headers() {
|
|||||||
", end_server.addr())
|
", end_server.addr())
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut cookie = reqwest::header::Cookie::new();
|
|
||||||
cookie.set("foo", "bar");
|
|
||||||
reqwest::Client::builder()
|
reqwest::Client::builder()
|
||||||
.referer(false)
|
.referer(false)
|
||||||
.build()
|
.build()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get(&format!("http://{}/sensitive", mid_server.addr()))
|
.get(&format!("http://{}/sensitive", mid_server.addr()))
|
||||||
.header(cookie)
|
.header(reqwest::header::COOKIE, reqwest::header::HeaderValue::from_static("foo=bar"))
|
||||||
.send()
|
.send()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
@@ -261,10 +256,10 @@ fn test_redirect_policy_can_return_errors() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /loop HTTP/1.1\r\n\
|
GET /loop HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -285,10 +280,10 @@ fn test_redirect_policy_can_stop_redirects_without_an_error() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /no-redirect HTTP/1.1\r\n\
|
GET /no-redirect HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -311,9 +306,8 @@ fn test_redirect_policy_can_stop_redirects_without_an_error() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(res.url().as_str(), url);
|
assert_eq!(res.url().as_str(), url);
|
||||||
assert_eq!(res.status(), reqwest::StatusCode::Found);
|
assert_eq!(res.status(), reqwest::StatusCode::FOUND);
|
||||||
assert_eq!(res.headers().get(),
|
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test-dont");
|
||||||
Some(&reqwest::header::Server::new("test-dont".to_string())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -321,10 +315,10 @@ fn test_referer_is_not_set_if_disabled() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /no-refer HTTP/1.1\r\n\
|
GET /no-refer HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -338,10 +332,10 @@ fn test_referer_is_not_set_if_disabled() {
|
|||||||
|
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /dst HTTP/1.1\r\n\
|
GET /dst HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ fn test_write_timeout() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
POST /write-timeout HTTP/1.1\r\n\
|
POST /write-timeout HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
Content-Length: 5\r\n\
|
accept: */*\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
content-length: 5\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
Hello\
|
Hello\
|
||||||
",
|
",
|
||||||
@@ -34,7 +34,7 @@ fn test_write_timeout() {
|
|||||||
.build()
|
.build()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.post(&url)
|
.post(&url)
|
||||||
.header(reqwest::header::ContentLength(5))
|
.header(reqwest::header::CONTENT_LENGTH, reqwest::header::HeaderValue::from_static("5"))
|
||||||
.body(reqwest::Body::new(&b"Hello"[..]))
|
.body(reqwest::Body::new(&b"Hello"[..]))
|
||||||
.send()
|
.send()
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
@@ -49,10 +49,10 @@ fn test_response_timeout() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /response-timeout HTTP/1.1\r\n\
|
GET /response-timeout HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -80,10 +80,10 @@ fn test_read_timeout() {
|
|||||||
let server = server! {
|
let server = server! {
|
||||||
request: b"\
|
request: b"\
|
||||||
GET /read-timeout HTTP/1.1\r\n\
|
GET /read-timeout HTTP/1.1\r\n\
|
||||||
Host: $HOST\r\n\
|
user-agent: $USERAGENT\r\n\
|
||||||
User-Agent: $USERAGENT\r\n\
|
accept: */*\r\n\
|
||||||
Accept: */*\r\n\
|
accept-encoding: gzip\r\n\
|
||||||
Accept-Encoding: gzip\r\n\
|
host: $HOST\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
",
|
",
|
||||||
response: b"\
|
response: b"\
|
||||||
@@ -105,9 +105,8 @@ fn test_read_timeout() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(res.url().as_str(), &url);
|
assert_eq!(res.url().as_str(), &url);
|
||||||
assert_eq!(res.status(), reqwest::StatusCode::Ok);
|
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||||
assert_eq!(res.headers().get(),
|
assert_eq!(res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(), &"5");
|
||||||
Some(&reqwest::header::ContentLength(5)));
|
|
||||||
|
|
||||||
let mut buf = [0; 1024];
|
let mut buf = [0; 1024];
|
||||||
let err = res.read(&mut buf).unwrap_err();
|
let err = res.read(&mut buf).unwrap_err();
|
||||||
|
|||||||
Reference in New Issue
Block a user