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