Reinstate read timeouts on body.

This feature was broken in #67, which reset timeouts on the
stream before passing it to set_stream.

As part of this change, refactor the internal storage of
timeouts on the Request object to use Option<Duration>.

Remove the deadline field on Response. It wasn't used. The
deadline field on unit was used instead.

Add a unittest.
This commit is contained in:
Jacob Hoffman-Andrews
2020-10-21 20:39:34 -07:00
committed by Martin Algesten
parent 32f9ebc04a
commit 2bf9362eff
4 changed files with 56 additions and 24 deletions

View File

@@ -1,7 +1,6 @@
use std::fmt;
use std::io::{self, Cursor, ErrorKind, Read};
use std::str::FromStr;
use std::time::Instant;
use chunked_transfer::Decoder as ChunkDecoder;
@@ -56,7 +55,6 @@ pub struct Response {
headers: Vec<Header>,
unit: Option<Unit>,
stream: Option<Stream>,
deadline: Option<Instant>,
}
/// index into status_line where we split: HTTP/1.1 200 OK
@@ -327,12 +325,17 @@ impl Response {
let stream = self.stream.expect("No reader in response?!");
let unit = self.unit;
if let Some(unit) = &unit {
let result = stream.set_read_timeout(unit.req.timeout_read);
if let Err(e) = result {
return Box::new(ErrorReader(e)) as Box<dyn Read + Send>;
}
}
let deadline = unit.as_ref().and_then(|u| u.deadline);
let stream = DeadlineStream::new(stream, deadline);
match (use_chunked, limit_bytes) {
(true, _) => Box::new(PoolReturnRead::new(unit, ChunkDecoder::new(stream)))
as Box<dyn Read + Send>,
(true, _) => Box::new(PoolReturnRead::new(unit, ChunkDecoder::new(stream))),
(false, Some(len)) => {
Box::new(PoolReturnRead::new(unit, LimitedRead::new(stream, len)))
}
@@ -505,7 +508,6 @@ impl Response {
headers,
unit: None,
stream: None,
deadline: None,
})
}
@@ -585,9 +587,6 @@ impl Into<Response> for Error {
/// *Internal API*
pub(crate) fn set_stream(resp: &mut Response, url: String, unit: Option<Unit>, stream: Stream) {
resp.url = Some(url);
if let Some(unit) = &unit {
resp.deadline = unit.deadline;
}
resp.unit = unit;
resp.stream = Some(stream);
}
@@ -813,3 +812,14 @@ mod tests {
assert_eq!(v, "Bad Status\n");
}
}
// ErrorReader returns an error for every read.
// The error is as close to a clone of the underlying
// io::Error as we can get.
struct ErrorReader(io::Error);
impl Read for ErrorReader {
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
Err(io::Error::new(self.0.kind(), self.0.to_string()))
}
}