Skip to content

Commit

Permalink
Merge pull request #257 from ducaale/emtpy-gzip-head-response
Browse files Browse the repository at this point in the history
Handle empty gzip responses with content-length > 0
  • Loading branch information
ducaale authored May 14, 2022
2 parents 13185bd + 580ae5d commit 898dc2e
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 31 deletions.
65 changes: 34 additions & 31 deletions src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,15 @@ pub fn get_compression_type(headers: &HeaderMap) -> Option<CompressionType> {

struct InnerReader<R: Read> {
reader: R,
has_read_data: bool,
has_errored: bool,
}

impl<R: Read> InnerReader<R> {
fn new(reader: R) -> Self {
InnerReader {
reader,
has_read_data: false,
has_errored: false,
}
}
Expand All @@ -66,7 +68,11 @@ impl<R: Read> InnerReader<R> {
impl<R: Read> Read for InnerReader<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self.reader.read(buf) {
Ok(len) => Ok(len),
Ok(0) => Ok(0),
Ok(len) => {
self.has_read_data = true;
Ok(len)
}
Err(e) => {
self.has_errored = true;
Err(e)
Expand All @@ -86,36 +92,33 @@ impl<R: Read> Read for Decoder<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self {
Decoder::PlainText(decoder) => decoder.read(buf),
Decoder::Gzip(decoder) => decoder.read(buf).map_err(|e| {
if decoder.get_ref().has_errored {
e
} else {
io::Error::new(
e.kind(),
format!("error decoding gzip response body: {}", e),
)
}
}),
Decoder::Deflate(decoder) => decoder.read(buf).map_err(|e| {
if decoder.get_ref().has_errored {
e
} else {
io::Error::new(
e.kind(),
format!("error decoding deflate response body: {}", e),
)
}
}),
Decoder::Brotli(decoder) => decoder.read(buf).map_err(|e| {
if decoder.get_ref().has_errored {
e
} else {
io::Error::new(
e.kind(),
format!("error decoding brotli response body: {}", e),
)
}
}),
Decoder::Gzip(decoder) => match decoder.read(buf) {
Ok(n) => Ok(n),
Err(e) if decoder.get_ref().has_errored => Err(e),
Err(_) if !decoder.get_ref().has_read_data => Ok(0),
Err(e) => Err(io::Error::new(
e.kind(),
format!("error decoding gzip response body: {}", e),
)),
},
Decoder::Deflate(decoder) => match decoder.read(buf) {
Ok(n) => Ok(n),
Err(e) if decoder.get_ref().has_errored => Err(e),
Err(_) if !decoder.get_ref().has_read_data => Ok(0),
Err(e) => Err(io::Error::new(
e.kind(),
format!("error decoding deflate response body: {}", e),
)),
},
Decoder::Brotli(decoder) => match decoder.read(buf) {
Ok(n) => Ok(n),
Err(e) if decoder.get_ref().has_errored => Err(e),
Err(_) if !decoder.get_ref().has_read_data => Ok(0),
Err(e) => Err(io::Error::new(
e.kind(),
format!("error decoding brotli response body: {}", e),
)),
},
}
}
}
Expand Down
25 changes: 25 additions & 0 deletions tests/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2869,3 +2869,28 @@ fn empty_response_with_content_encoding() {
"#});
}

#[test]
fn empty_response_with_content_encoding_and_content_length() {
let server = server::http(|_req| async move {
hyper::Response::builder()
.header("date", "N/A")
.header("content-encoding", "gzip")
.header("content-length", "100")
.body("".into())
.unwrap()
});

get_command()
.arg("head")
.arg(server.base_url())
.assert()
.stdout(indoc! {r#"
HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Length: 100
Date: N/A
"#});
}

0 comments on commit 898dc2e

Please sign in to comment.