no body on HEAD request
This commit is contained in:
@@ -34,6 +34,8 @@ impl ConnectionPool {
|
|||||||
|
|
||||||
let is_secure = url.scheme().eq_ignore_ascii_case("https");
|
let is_secure = url.scheme().eq_ignore_ascii_case("https");
|
||||||
|
|
||||||
|
let is_head = request.method.eq_ignore_ascii_case("head");
|
||||||
|
|
||||||
let cookie_headers: Vec<_> = {
|
let cookie_headers: Vec<_> = {
|
||||||
match jar.as_ref() {
|
match jar.as_ref() {
|
||||||
None => vec![],
|
None => vec![],
|
||||||
@@ -131,7 +133,7 @@ impl ConnectionPool {
|
|||||||
send_body(body, do_chunk, &mut stream)?;
|
send_body(body, do_chunk, &mut stream)?;
|
||||||
|
|
||||||
// since it is not a redirect, give away the incoming stream to the response object
|
// since it is not a redirect, give away the incoming stream to the response object
|
||||||
resp.set_stream(stream);
|
resp.set_stream(stream, is_head);
|
||||||
|
|
||||||
// release the response
|
// release the response
|
||||||
Ok(resp)
|
Ok(resp)
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ pub struct Response {
|
|||||||
index: (usize, usize), // index into status_line where we split: HTTP/1.1 200 OK
|
index: (usize, usize), // index into status_line where we split: HTTP/1.1 200 OK
|
||||||
status: u16,
|
status: u16,
|
||||||
headers: Vec<Header>,
|
headers: Vec<Header>,
|
||||||
|
is_head: bool,
|
||||||
stream: Option<Stream>,
|
stream: Option<Stream>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,12 +243,22 @@ impl Response {
|
|||||||
/// assert_eq!(bytes.len(), len);
|
/// assert_eq!(bytes.len(), len);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn into_reader(self) -> impl Read {
|
pub fn into_reader(self) -> impl Read {
|
||||||
|
|
||||||
let is_chunked = self.header("transfer-encoding")
|
let is_chunked = self.header("transfer-encoding")
|
||||||
.map(|enc| enc.len() > 0) // whatever it says, do chunked
|
.map(|enc| enc.len() > 0) // whatever it says, do chunked
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
let len = self.header("content-length")
|
let len = self.header("content-length")
|
||||||
.and_then(|l| l.parse::<usize>().ok());
|
.and_then(|l| l.parse::<usize>().ok());
|
||||||
|
|
||||||
let reader = self.stream.expect("No reader in response?!");
|
let reader = self.stream.expect("No reader in response?!");
|
||||||
|
|
||||||
|
// head requests never have a body
|
||||||
|
if self.is_head {
|
||||||
|
return Box::new(LimitedRead::new(reader, 0)) as Box<Read>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// figure out how to make a reader
|
||||||
match is_chunked {
|
match is_chunked {
|
||||||
true => Box::new(chunked_transfer::Decoder::new(reader)),
|
true => Box::new(chunked_transfer::Decoder::new(reader)),
|
||||||
false => match len {
|
false => match len {
|
||||||
@@ -372,11 +383,13 @@ impl Response {
|
|||||||
index,
|
index,
|
||||||
status,
|
status,
|
||||||
headers,
|
headers,
|
||||||
|
is_head: false,
|
||||||
stream: None,
|
stream: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_stream(&mut self, stream: Stream) {
|
fn set_stream(&mut self, stream: Stream, is_head: bool) {
|
||||||
|
self.is_head = is_head;
|
||||||
self.stream = Some(stream);
|
self.stream = Some(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,7 +431,7 @@ impl FromStr for Response {
|
|||||||
let bytes = s.as_bytes().to_owned();
|
let bytes = s.as_bytes().to_owned();
|
||||||
let mut cursor = Cursor::new(bytes);
|
let mut cursor = Cursor::new(bytes);
|
||||||
let mut resp = Self::do_from_read(&mut cursor)?;
|
let mut resp = Self::do_from_read(&mut cursor)?;
|
||||||
resp.set_stream(Stream::Cursor(cursor));
|
resp.set_stream(Stream::Cursor(cursor), false);
|
||||||
Ok(resp)
|
Ok(resp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,3 +60,23 @@ fn ignore_content_length_when_chunked() {
|
|||||||
reader.read_to_string(&mut text).unwrap();
|
reader.read_to_string(&mut text).unwrap();
|
||||||
assert_eq!(text, "hello world!!!");
|
assert_eq!(text, "hello world!!!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_reader_on_head() {
|
||||||
|
test::set_handler("/no_reader_on_head", |_req, _url| {
|
||||||
|
// so this is technically illegal, we return a body for the HEAD request.
|
||||||
|
test::make_response(
|
||||||
|
200,
|
||||||
|
"OK",
|
||||||
|
vec!["Content-Length: 4", "transfer-encoding: chunked"],
|
||||||
|
"3\r\nhel\r\nb\r\nlo world!!!\r\n0\r\n\r\n"
|
||||||
|
.to_string()
|
||||||
|
.into_bytes(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
let resp = head("test://host/no_reader_on_head").call();
|
||||||
|
let mut reader = resp.into_reader();
|
||||||
|
let mut text = String::new();
|
||||||
|
reader.read_to_string(&mut text).unwrap();
|
||||||
|
assert_eq!(text, "");
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user