From 580ae5d90639d894d8e442656710f6af27305ca0 Mon Sep 17 00:00:00 2001 From: ducaale Date: Sat, 14 May 2022 19:35:57 +0100 Subject: [PATCH] handle empty gzip responses with content-length > 0 --- src/decoder.rs | 65 ++++++++++++++++++++++++++------------------------ tests/cli.rs | 25 +++++++++++++++++++ 2 files changed, 59 insertions(+), 31 deletions(-) diff --git a/src/decoder.rs b/src/decoder.rs index e257ef1f..8b91aa0c 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -51,6 +51,7 @@ pub fn get_compression_type(headers: &HeaderMap) -> Option { struct InnerReader { reader: R, + has_read_data: bool, has_errored: bool, } @@ -58,6 +59,7 @@ impl InnerReader { fn new(reader: R) -> Self { InnerReader { reader, + has_read_data: false, has_errored: false, } } @@ -66,7 +68,11 @@ impl InnerReader { impl Read for InnerReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { 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) @@ -86,36 +92,33 @@ impl Read for Decoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { 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), + )), + }, } } } diff --git a/tests/cli.rs b/tests/cli.rs index 3f5224ee..4a7d88d1 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -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 + + + "#}); +}