content limited and bogus chunk

This commit is contained in:
Martin Algesten
2018-06-11 21:59:37 +02:00
parent 5be3aef553
commit 4ca0914f9a
3 changed files with 85 additions and 2 deletions

View File

@@ -132,12 +132,18 @@ impl Response {
pub fn into_reader(self) -> impl Read { pub fn into_reader(self) -> impl Read {
let is_chunked = self.get("transfer-encoding") let is_chunked = self.get("transfer-encoding")
.map(|enc| enc.eq_ignore_ascii_case("chunked")) .map(|enc| enc.len() > 0) // whatever it says, do chunked
.unwrap_or(false); .unwrap_or(false);
let len = self.get("content-length").and_then(|l| l.parse::<usize>().ok());
let reader = self.reader.expect("No reader in response?!"); let reader = self.reader.expect("No reader in response?!");
match is_chunked { match is_chunked {
true => Box::new(chunked_transfer::Decoder::new(reader)), true => Box::new(chunked_transfer::Decoder::new(reader)),
false => reader, false => {
match len {
Some(len) => Box::new(LimitedRead::new(reader, len)),
None => reader,
}
},
} }
} }
@@ -273,3 +279,37 @@ fn read_next_line<R: Read>(reader: &mut R) -> IoResult<AsciiString> {
buf.push(byte); buf.push(byte);
} }
} }
struct LimitedRead {
reader: Box<Read + Send>,
limit: usize,
position: usize,
}
impl LimitedRead {
fn new(reader: Box<Read + Send>, limit: usize) -> Self {
LimitedRead {
reader,
limit,
position: 0,
}
}
}
impl Read for LimitedRead {
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
let left = self.limit - self.position;
let from = if left < buf.len() {
&mut buf[0..left]
} else {
buf
};
match self.reader.read(from) {
Ok(amount) => {
self.position += amount;
Ok(amount)
},
Err(e) => Err(e)
}
}
}

42
src/test/body_read.rs Normal file
View File

@@ -0,0 +1,42 @@
use std::io::Read;
use test;
use super::super::*;
#[test]
fn transfer_encoding_bogus() {
test::set_handler("/transfer_encoding_bogus", |_req, _url| {
test::make_stream(
200,
"OK",
vec![
"transfer-encoding: bogus", // whatever it says here, we should chunk
],
"3\r\nhel\r\nb\r\nlo world!!!\r\n0\r\n\r\n"
.to_string()
.into_bytes(),
)
});
let resp = get("test://host/transfer_encoding_bogus").call();
let mut reader = resp.into_reader();
let mut text = String::new();
reader.read_to_string(&mut text).unwrap();
assert_eq!(text, "hello world!!!");
}
#[test]
fn content_length_limited() {
test::set_handler("/content_length_limited", |_req, _url| {
test::make_stream(
200,
"OK",
vec!["Content-Length: 4"],
"abcdefgh".to_string().into_bytes(),
)
});
let resp = get("test://host/content_length_limited").call();
let mut reader = resp.into_reader();
let mut text = String::new();
reader.read_to_string(&mut text).unwrap();
assert_eq!(text, "abcd");
}

View File

@@ -9,6 +9,7 @@ use url::Url;
use util::vecread::VecRead; use util::vecread::VecRead;
mod simple; mod simple;
mod body_read;
type RequestHandler = Fn(&Request, &Url) -> Result<Stream, Error> + Send + 'static; type RequestHandler = Fn(&Request, &Url) -> Result<Stream, Error> + Send + 'static;