upgrade hyper to v0.11

This commit is contained in:
Sean McArthur
2017-06-20 21:27:59 -07:00
parent 8633060eaf
commit 665b4fe718
26 changed files with 2647 additions and 1027 deletions

View File

@@ -1,11 +1,9 @@
extern crate reqwest;
extern crate libflate;
#[macro_use]
mod server;
mod support;
use std::io::Read;
use std::io::prelude::*;
#[test]
fn test_get() {
@@ -32,7 +30,7 @@ fn test_get() {
assert_eq!(res.url().as_str(), &url);
assert_eq!(res.status(), reqwest::StatusCode::Ok);
assert_eq!(res.headers().get(),
Some(&reqwest::header::Server("test".to_string())));
Some(&reqwest::header::Server::new("test".to_string())));
assert_eq!(res.headers().get(),
Some(&reqwest::header::ContentLength(0)));
@@ -42,473 +40,43 @@ fn test_get() {
}
#[test]
fn test_redirect_301_and_302_and_303_changes_post_to_get() {
let client = reqwest::Client::new().unwrap();
let codes = [301, 302, 303];
for code in codes.iter() {
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\
Content-Length: 0\r\n\
\r\n\
", code),
response: format!("\
HTTP/1.1 {} reason\r\n\
Server: test-redirect\r\n\
Content-Length: 0\r\n\
Location: /dst\r\n\
Connection: close\r\n\
\r\n\
", code),
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\
\r\n\
", code),
response: b"\
HTTP/1.1 200 OK\r\n\
Server: test-dst\r\n\
Content-Length: 0\r\n\
\r\n\
"
};
let url = format!("http://{}/{}", redirect.addr(), code);
let dst = format!("http://{}/{}", redirect.addr(), "dst");
let res = client.post(&url)
.unwrap()
.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("test-dst".to_string())));
}
}
#[test]
fn test_redirect_307_and_308_tries_to_post_again() {
let client = reqwest::Client::new().unwrap();
let codes = [307, 308];
for code in codes.iter() {
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\
Content-Length: 5\r\n\
\r\n\
Hello\
", code),
response: format!("\
HTTP/1.1 {} reason\r\n\
Server: test-redirect\r\n\
Content-Length: 0\r\n\
Location: /dst\r\n\
Connection: close\r\n\
\r\n\
", code),
request: format!("\
POST /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\
Content-Length: 5\r\n\
\r\n\
Hello\
", code),
response: b"\
HTTP/1.1 200 OK\r\n\
Server: test-dst\r\n\
Content-Length: 0\r\n\
\r\n\
"
};
let url = format!("http://{}/{}", redirect.addr(), code);
let dst = format!("http://{}/{}", redirect.addr(), "dst");
let res = client.post(&url)
.unwrap()
.body("Hello")
.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("test-dst".to_string())));
}
}
#[test]
fn test_redirect_307_does_not_try_if_reader_cannot_reset() {
let client = reqwest::Client::new().unwrap();
let codes = [307, 308];
for &code in codes.iter() {
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\
\r\n\
5\r\n\
Hello\r\n\
0\r\n\r\n\
", code),
response: format!("\
HTTP/1.1 {} reason\r\n\
Server: test-redirect\r\n\
Content-Length: 0\r\n\
Location: /dst\r\n\
Connection: close\r\n\
\r\n\
", code)
};
let url = format!("http://{}/{}", redirect.addr(), code);
let res = client
.post(&url)
.unwrap()
.body(reqwest::Body::new(&b"Hello"[..]))
.send()
.unwrap();
assert_eq!(res.url().as_str(), url);
assert_eq!(res.status(), reqwest::StatusCode::from_u16(code));
}
}
#[test]
fn test_redirect_removes_sensitive_headers() {
let end_server = server! {
fn test_post() {
let server = server! {
request: b"\
GET /otherhost HTTP/1.1\r\n\
POST /2 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\
\r\n\
Hello\
",
response: b"\
HTTP/1.1 200 OK\r\n\
Server: test\r\n\
Server: post\r\n\
Content-Length: 0\r\n\
\r\n\
"
};
let mid_server = server! {
request: b"\
GET /sensitive HTTP/1.1\r\n\
Host: $HOST\r\n\
Cookie: foo=bar\r\n\
User-Agent: $USERAGENT\r\n\
Accept: */*\r\n\
Accept-Encoding: gzip\r\n\
\r\n\
",
response: format!("\
HTTP/1.1 302 Found\r\n\
Server: test\r\n\
Location: http://{}/otherhost\r\n\
Content-Length: 0\r\n\
\r\n\
", end_server.addr())
};
reqwest::Client::builder()
let url = format!("http://{}/2", server.addr());
let mut res = reqwest::Client::new()
.unwrap()
.referer(false)
.build()
.unwrap()
.get(&format!("http://{}/sensitive", mid_server.addr()))
.unwrap()
.header(reqwest::header::Cookie(vec![String::from("foo=bar")]))
.send()
.unwrap();
}
#[test]
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\
\r\n\
",
response: b"\
HTTP/1.1 302 Found\r\n\
Server: test\r\n\
Location: /loop\r\n\
Content-Length: 0\r\n\
\r\n\
"
};
let err = reqwest::get(&format!("http://{}/loop", server.addr())).unwrap_err();
assert!(err.is_redirect());
}
#[test]
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\
\r\n\
",
response: b"\
HTTP/1.1 302 Found\r\n\
Server: test-dont\r\n\
Location: /dont\r\n\
Content-Length: 0\r\n\
\r\n\
"
};
let url = format!("http://{}/no-redirect", server.addr());
let res = reqwest::Client::builder()
.unwrap()
.redirect(reqwest::RedirectPolicy::none())
.build()
.unwrap()
.get(&url)
.post(&url)
.unwrap()
.body("Hello")
.send()
.unwrap();
assert_eq!(res.url().as_str(), url);
assert_eq!(res.status(), reqwest::StatusCode::Found);
assert_eq!(res.url().as_str(), &url);
assert_eq!(res.status(), reqwest::StatusCode::Ok);
assert_eq!(res.headers().get(),
Some(&reqwest::header::Server("test-dont".to_string())));
}
#[test]
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\
\r\n\
",
response: b"\
HTTP/1.1 302 Found\r\n\
Server: test-no-referer\r\n\
Content-Length: 0\r\n\
Location: /dst\r\n\
Connection: close\r\n\
\r\n\
",
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\
\r\n\
",
response: b"\
HTTP/1.1 200 OK\r\n\
Server: test-dst\r\n\
Content-Length: 0\r\n\
\r\n\
"
};
reqwest::Client::builder().unwrap()
.referer(false)
.build().unwrap()
//client
.get(&format!("http://{}/no-refer", server.addr()))
.unwrap()
.send()
.unwrap();
}
#[test]
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\
Accept: application/json\r\n\
User-Agent: $USERAGENT\r\n\
Accept-Encoding: gzip\r\n\
\r\n\
",
response: b"\
HTTP/1.1 200 OK\r\n\
Server: test-accept\r\n\
Content-Length: 0\r\n\
\r\n\
"
};
let client = reqwest::Client::new().unwrap();
let res = client
.get(&format!("http://{}/accept", server.addr()))
.unwrap()
.header(reqwest::header::Accept::json())
.send()
.unwrap();
assert_eq!(res.status(), reqwest::StatusCode::Ok);
}
#[test]
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\
Accept-Encoding: identity\r\n\
User-Agent: $USERAGENT\r\n\
Accept: */*\r\n\
\r\n\
",
response: b"\
HTTP/1.1 200 OK\r\n\
Server: test-accept-encoding\r\n\
Content-Length: 0\r\n\
\r\n\
"
};
let client = reqwest::Client::new().unwrap();
let res = client.get(&format!("http://{}/accept-encoding", server.addr()))
.unwrap()
.header(reqwest::header::AcceptEncoding(
vec![reqwest::header::qitem(reqwest::header::Encoding::Identity)]
))
.send()
.unwrap();
assert_eq!(res.status(), reqwest::StatusCode::Ok);
}
#[test]
fn test_gzip_response() {
let mut encoder = ::libflate::gzip::Encoder::new(Vec::new()).unwrap();
match encoder.write(b"test request") {
Ok(n) => assert!(n > 0, "Failed to write to encoder."),
_ => panic!("Failed to gzip encode string."),
};
let gzipped_content = encoder.finish().into_result().unwrap();
let mut response = format!("\
HTTP/1.1 200 OK\r\n\
Server: test-accept\r\n\
Content-Encoding: gzip\r\n\
Content-Length: {}\r\n\
\r\n", &gzipped_content.len())
.into_bytes();
response.extend(&gzipped_content);
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\
\r\n\
",
response: response
};
let mut res = reqwest::get(&format!("http://{}/gzip", server.addr())).unwrap();
let mut body = ::std::string::String::new();
match res.read_to_string(&mut body) {
Ok(n) => assert!(n > 0, "Failed to write to buffer."),
_ => panic!("Failed to write to buffer."),
};
assert_eq!(body, "test request");
}
#[test]
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\
\r\n\
",
response: b"\
HTTP/1.1 200 OK\r\n\
Server: test-accept\r\n\
Content-Encoding: gzip\r\n\
Content-Length: 100\r\n\
\r\n"
};
let client = reqwest::Client::new().unwrap();
let mut res = client
.head(&format!("http://{}/gzip", server.addr()))
.unwrap()
.send()
.unwrap();
let mut body = ::std::string::String::new();
res.read_to_string(&mut body).unwrap();
assert_eq!(body, "");
}
#[test]
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\
\r\n\
",
response: b"\
HTTP/1.1 200 OK\r\n\
Server: test-accept\r\n\
Content-Encoding: gzip\r\n\
Content-Length: 100\r\n\
\r\n\
0"
};
let mut res = reqwest::get(&format!("http://{}/gzip", server.addr())).unwrap();
// this tests that the request.send() didn't error, but that the error
// is in reading the body
let mut body = ::std::string::String::new();
res.read_to_string(&mut body).unwrap_err();
Some(&reqwest::header::Server::new("post")));
assert_eq!(res.headers().get(),
Some(&reqwest::header::ContentLength(0)));
let mut buf = [0; 1024];
let n = res.read(&mut buf).unwrap();
assert_eq!(n, 0)
}

166
tests/gzip.rs Normal file
View File

@@ -0,0 +1,166 @@
extern crate reqwest;
extern crate libflate;
#[macro_use]
mod support;
use std::io::{Read, Write};
#[test]
fn test_gzip_response() {
let mut encoder = ::libflate::gzip::Encoder::new(Vec::new()).unwrap();
match encoder.write(b"test request") {
Ok(n) => assert!(n > 0, "Failed to write to encoder."),
_ => panic!("Failed to gzip encode string."),
};
let gzipped_content = encoder.finish().into_result().unwrap();
let mut response = format!("\
HTTP/1.1 200 OK\r\n\
Server: test-accept\r\n\
Content-Encoding: gzip\r\n\
Content-Length: {}\r\n\
\r\n", &gzipped_content.len())
.into_bytes();
response.extend(&gzipped_content);
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\
\r\n\
",
response: response
};
let mut res = reqwest::get(&format!("http://{}/gzip", server.addr())).unwrap();
let mut body = String::new();
res.read_to_string(&mut body).unwrap();
assert_eq!(body, "test request");
}
#[test]
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\
\r\n\
",
response: b"\
HTTP/1.1 200 OK\r\n\
Server: test-accept\r\n\
Content-Encoding: gzip\r\n\
Content-Length: 100\r\n\
\r\n"
};
let client = reqwest::Client::new().unwrap();
let mut res = client
.head(&format!("http://{}/gzip", server.addr()))
.unwrap()
.send()
.unwrap();
let mut body = ::std::string::String::new();
res.read_to_string(&mut body).unwrap();
assert_eq!(body, "");
}
#[test]
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\
\r\n\
",
response: b"\
HTTP/1.1 200 OK\r\n\
Server: test-accept\r\n\
Content-Encoding: gzip\r\n\
Content-Length: 100\r\n\
\r\n\
0"
};
let mut res = reqwest::get(&format!("http://{}/gzip", server.addr())).unwrap();
// this tests that the request.send() didn't error, but that the error
// is in reading the body
let mut body = ::std::string::String::new();
res.read_to_string(&mut body).unwrap_err();
}
#[test]
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\
Accept: application/json\r\n\
User-Agent: $USERAGENT\r\n\
Accept-Encoding: gzip\r\n\
\r\n\
",
response: b"\
HTTP/1.1 200 OK\r\n\
Server: test-accept\r\n\
Content-Length: 0\r\n\
\r\n\
"
};
let client = reqwest::Client::new().unwrap();
let res = client
.get(&format!("http://{}/accept", server.addr()))
.unwrap()
.header(reqwest::header::Accept::json())
.send()
.unwrap();
assert_eq!(res.status(), reqwest::StatusCode::Ok);
}
#[test]
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\
Accept-Encoding: identity\r\n\
User-Agent: $USERAGENT\r\n\
Accept: */*\r\n\
\r\n\
",
response: b"\
HTTP/1.1 200 OK\r\n\
Server: test-accept-encoding\r\n\
Content-Length: 0\r\n\
\r\n\
"
};
let client = reqwest::Client::new().unwrap();
let res = client.get(&format!("http://{}/accept-encoding", server.addr()))
.unwrap()
.header(reqwest::header::AcceptEncoding(
vec![reqwest::header::qitem(reqwest::header::Encoding::Identity)]
))
.send()
.unwrap();
assert_eq!(res.status(), reqwest::StatusCode::Ok);
}

318
tests/redirect.rs Normal file
View File

@@ -0,0 +1,318 @@
extern crate reqwest;
#[macro_use]
mod support;
#[test]
fn test_redirect_301_and_302_and_303_changes_post_to_get() {
let client = reqwest::Client::new().unwrap();
let codes = [301, 302, 303];
for code in codes.iter() {
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\
Content-Length: 0\r\n\
\r\n\
", code),
response: format!("\
HTTP/1.1 {} reason\r\n\
Server: test-redirect\r\n\
Content-Length: 0\r\n\
Location: /dst\r\n\
Connection: close\r\n\
\r\n\
", code),
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\
\r\n\
", code),
response: b"\
HTTP/1.1 200 OK\r\n\
Server: test-dst\r\n\
Content-Length: 0\r\n\
\r\n\
"
};
let url = format!("http://{}/{}", redirect.addr(), code);
let dst = format!("http://{}/{}", redirect.addr(), "dst");
let res = client.post(&url)
.unwrap()
.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())));
}
}
#[test]
fn test_redirect_307_and_308_tries_to_post_again() {
let client = reqwest::Client::new().unwrap();
let codes = [307, 308];
for code in codes.iter() {
let redirect = server! {
request: format!("\
POST /{} 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\
\r\n\
Hello\
", code),
response: format!("\
HTTP/1.1 {} reason\r\n\
Server: test-redirect\r\n\
Content-Length: 0\r\n\
Location: /dst\r\n\
Connection: close\r\n\
\r\n\
", code),
request: format!("\
POST /dst 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\
Referer: http://$HOST/{}\r\n\
\r\n\
Hello\
", code),
response: b"\
HTTP/1.1 200 OK\r\n\
Server: test-dst\r\n\
Content-Length: 0\r\n\
\r\n\
"
};
let url = format!("http://{}/{}", redirect.addr(), code);
let dst = format!("http://{}/{}", redirect.addr(), "dst");
let res = client.post(&url)
.unwrap()
.body("Hello")
.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())));
}
}
/*
#[test]
fn test_redirect_307_does_not_try_if_reader_cannot_reset() {
let client = reqwest::Client::new().unwrap();
let codes = [307, 308];
for &code in codes.iter() {
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\
\r\n\
5\r\n\
Hello\r\n\
0\r\n\r\n\
", code),
response: format!("\
HTTP/1.1 {} reason\r\n\
Server: test-redirect\r\n\
Content-Length: 0\r\n\
Location: /dst\r\n\
Connection: close\r\n\
\r\n\
", code)
};
let url = format!("http://{}/{}", redirect.addr(), code);
let res = client
.post(&url)
.unwrap()
.body(reqwest::Body::new(&b"Hello"[..]))
.send()
.unwrap();
assert_eq!(res.url().as_str(), url);
assert_eq!(res.status(), reqwest::StatusCode::try_from(code).unwrap());
}
}
*/
#[test]
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\
\r\n\
",
response: b"\
HTTP/1.1 200 OK\r\n\
Server: test\r\n\
Content-Length: 0\r\n\
\r\n\
"
};
let mid_server = server! {
request: b"\
GET /sensitive HTTP/1.1\r\n\
Host: $HOST\r\n\
Cookie: foo=bar\r\n\
User-Agent: $USERAGENT\r\n\
Accept: */*\r\n\
Accept-Encoding: gzip\r\n\
\r\n\
",
response: format!("\
HTTP/1.1 302 Found\r\n\
Server: test\r\n\
Location: http://{}/otherhost\r\n\
Content-Length: 0\r\n\
\r\n\
", end_server.addr())
};
let mut cookie = reqwest::header::Cookie::new();
cookie.set("foo", "bar");
reqwest::Client::builder()
.unwrap()
.referer(false)
.build()
.unwrap()
.get(&format!("http://{}/sensitive", mid_server.addr()))
.unwrap()
.header(cookie)
.send()
.unwrap();
}
#[test]
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\
\r\n\
",
response: b"\
HTTP/1.1 302 Found\r\n\
Server: test\r\n\
Location: /loop\r\n\
Content-Length: 0\r\n\
\r\n\
"
};
let err = reqwest::get(&format!("http://{}/loop", server.addr())).unwrap_err();
assert!(err.is_redirect());
}
#[test]
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\
\r\n\
",
response: b"\
HTTP/1.1 302 Found\r\n\
Server: test-dont\r\n\
Location: /dont\r\n\
Content-Length: 0\r\n\
\r\n\
"
};
let url = format!("http://{}/no-redirect", server.addr());
let res = reqwest::Client::builder()
.unwrap()
.redirect(reqwest::RedirectPolicy::none())
.build()
.unwrap()
.get(&url)
.unwrap()
.send()
.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())));
}
#[test]
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\
\r\n\
",
response: b"\
HTTP/1.1 302 Found\r\n\
Server: test-no-referer\r\n\
Content-Length: 0\r\n\
Location: /dst\r\n\
Connection: close\r\n\
\r\n\
",
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\
\r\n\
",
response: b"\
HTTP/1.1 200 OK\r\n\
Server: test-dst\r\n\
Content-Length: 0\r\n\
\r\n\
"
};
reqwest::Client::builder().unwrap()
.referer(false)
.build().unwrap()
//client
.get(&format!("http://{}/no-refer", server.addr()))
.unwrap()
.send()
.unwrap();
}

2
tests/support/mod.rs Normal file
View File

@@ -0,0 +1,2 @@
#[macro_use]
pub mod server;

View File

@@ -2,6 +2,7 @@
use std::io::{Read, Write};
use std::net;
use std::time::Duration;
use std::thread;
pub struct Server {
@@ -14,16 +15,33 @@ impl Server {
}
}
#[derive(Default)]
pub struct Txn {
pub request: Vec<u8>,
pub response: Vec<u8>,
pub read_timeout: Option<Duration>,
pub response_timeout: Option<Duration>,
pub write_timeout: Option<Duration>,
}
static DEFAULT_USER_AGENT: &'static str =
concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"));
pub fn spawn(txns: Vec<(Vec<u8>, Vec<u8>)>) -> Server {
pub fn spawn(txns: Vec<Txn>) -> Server {
let listener = net::TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.local_addr().unwrap();
thread::spawn(
move || for (mut expected, reply) in txns {
move || for txn in txns {
let mut expected = txn.request;
let reply = txn.response;
let (mut socket, _addr) = listener.accept().unwrap();
replace_expected_vars(&mut expected, addr.to_string().as_ref(), DEFAULT_USER_AGENT.as_ref());
if let Some(dur) = txn.read_timeout {
thread::park_timeout(dur);
}
let mut buf = [0; 4096];
let n = socket.read(&mut buf).unwrap();
@@ -31,7 +49,19 @@ pub fn spawn(txns: Vec<(Vec<u8>, Vec<u8>)>) -> Server {
(Ok(expected), Ok(received)) => assert_eq!(expected, received),
_ => assert_eq!(expected, &buf[..n]),
}
socket.write_all(&reply).unwrap();
if let Some(dur) = txn.response_timeout {
thread::park_timeout(dur);
}
if let Some(dur) = txn.write_timeout {
let headers_end = ::std::str::from_utf8(&reply).unwrap().find("\r\n\r\n").unwrap() + 4;
socket.write_all(&reply[..headers_end]).unwrap();
thread::park_timeout(dur);
socket.write_all(&reply[headers_end..]).unwrap();
} else {
socket.write_all(&reply).unwrap();
}
}
);
@@ -76,9 +106,38 @@ fn replace_expected_vars(bytes: &mut Vec<u8>, host: &[u8], ua: &[u8]) {
#[macro_export]
macro_rules! server {
($(request: $req:expr, response: $res:expr),*) => ({
server!($(request: $req, response: $res;)*)
});
($($($f:ident: $v:expr),*);*) => ({
let txns = vec![
$(((&$req[..]).into(), (&$res[..]).into()),)*
$(__internal__txn! {
$($f: $v,)*
}),*
];
::server::spawn(txns)
::support::server::spawn(txns)
})
}
#[macro_export]
macro_rules! __internal__txn {
($($field:ident: $val:expr,)*) => (
::support::server::Txn {
$( $field: __internal__prop!($field: $val), )*
.. Default::default()
}
)
}
#[macro_export]
macro_rules! __internal__prop {
(request: $val:expr) => (
From::from(&$val[..])
);
(response: $val:expr) => (
From::from(&$val[..])
);
($field:ident: $val:expr) => (
From::from($val)
)
}

121
tests/timeouts.rs Normal file
View File

@@ -0,0 +1,121 @@
extern crate reqwest;
#[macro_use]
mod support;
use std::io::Read;
use std::time::Duration;
#[test]
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\
\r\n\
Hello\
",
response: b"\
HTTP/1.1 200 OK\r\n\
Content-Length: 5\r\n\
\r\n\
Hello\
",
read_timeout: Duration::from_secs(1)
};
let url = format!("http://{}/write-timeout", server.addr());
let err = reqwest::Client::builder()
.unwrap()
.timeout(Duration::from_millis(500))
.build()
.unwrap()
.post(&url)
.unwrap()
.header(reqwest::header::ContentLength(5))
.body(reqwest::Body::new(&b"Hello"[..]))
.send()
.unwrap_err();
assert_eq!(err.get_ref().unwrap().to_string(), "timed out");
assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str()));
}
#[test]
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\
\r\n\
",
response: b"\
HTTP/1.1 200 OK\r\n\
Content-Length: 0\r\n\
",
response_timeout: Duration::from_secs(1)
};
let url = format!("http://{}/response-timeout", server.addr());
let err = reqwest::Client::builder()
.unwrap()
.timeout(Duration::from_millis(500))
.build()
.unwrap()
.get(&url)
.unwrap()
.send()
.unwrap_err();
assert_eq!(err.get_ref().unwrap().to_string(), "timed out");
assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str()));
}
#[test]
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\
\r\n\
",
response: b"\
HTTP/1.1 200 OK\r\n\
Content-Length: 5\r\n\
\r\n\
Hello\
",
write_timeout: Duration::from_secs(1)
};
let url = format!("http://{}/read-timeout", server.addr());
let mut res = reqwest::Client::builder()
.unwrap()
.timeout(Duration::from_millis(500))
.build()
.unwrap()
.get(&url)
.unwrap()
.send()
.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)));
let mut buf = [0; 1024];
let err = res.read(&mut buf).unwrap_err();
assert_eq!(err.to_string(), "timed out");
}