Skip to content

Commit

Permalink
Support x-gzip as Accept-Encoding in Compression (#466) (#467)
Browse files Browse the repository at this point in the history
  • Loading branch information
privettoli authored Feb 15, 2024
1 parent 601ba88 commit e0192a3
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 2 deletions.
42 changes: 41 additions & 1 deletion tower-http/src/compression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ mod tests {
use http::header::{
ACCEPT_ENCODING, ACCEPT_RANGES, CONTENT_ENCODING, CONTENT_RANGE, CONTENT_TYPE, RANGE,
};
use http::{HeaderMap, HeaderName, Request, Response};
use http::{HeaderMap, HeaderName, HeaderValue, Request, Response};
use http_body_util::BodyExt;
use std::convert::Infallible;
use std::io::Read;
Expand Down Expand Up @@ -150,6 +150,46 @@ mod tests {
assert_eq!(trailers["foo"], "bar");
}

#[tokio::test]
async fn x_gzip_works() {
let svc = service_fn(handle);
let mut svc = Compression::new(svc).compress_when(Always);

// call the service
let req = Request::builder()
.header("accept-encoding", "x-gzip")
.body(Body::empty())
.unwrap();
let res = svc.ready().await.unwrap().call(req).await.unwrap();

// we treat x-gzip as equivalent to gzip and don't have to return x-gzip
// taking extra caution by checking all headers with this name
assert_eq!(
res.headers()
.get_all("content-encoding")
.iter()
.collect::<Vec<&HeaderValue>>(),
vec!(HeaderValue::from_static("gzip"))
);

// read the compressed body
let collected = res.into_body().collect().await.unwrap();
let trailers = collected.trailers().cloned().unwrap();
let compressed_data = collected.to_bytes();

// decompress the body
// doing this with flate2 as that is much easier than async-compression and blocking during
// tests is fine
let mut decoder = GzDecoder::new(&compressed_data[..]);
let mut decompressed = String::new();
decoder.read_to_string(&mut decompressed).unwrap();

assert_eq!(decompressed, "Hello, World!");

// trailers are maintained
assert_eq!(trailers["foo"], "bar");
}

#[tokio::test]
async fn zstd_works() {
let svc = service_fn(handle);
Expand Down
26 changes: 25 additions & 1 deletion tower-http/src/content_encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ impl Encoding {
))]
fn parse(s: &str, _supported_encoding: impl SupportedEncodings) -> Option<Encoding> {
#[cfg(any(feature = "fs", feature = "compression-gzip"))]
if s.eq_ignore_ascii_case("gzip") && _supported_encoding.gzip() {
if (s.eq_ignore_ascii_case("gzip") || s.eq_ignore_ascii_case("x-gzip"))
&& _supported_encoding.gzip()
{
return Some(Encoding::Gzip);
}

Expand Down Expand Up @@ -297,6 +299,28 @@ mod tests {
assert_eq!(Encoding::Brotli, encoding);
}

#[test]
fn accept_encoding_header_gzip_x_gzip() {
let mut headers = http::HeaderMap::new();
headers.append(
http::header::ACCEPT_ENCODING,
http::HeaderValue::from_static("gzip,x-gzip"),
);
let encoding = Encoding::from_headers(&headers, SupportedEncodingsAll);
assert_eq!(Encoding::Gzip, encoding);
}

#[test]
fn accept_encoding_header_x_gzip_deflate() {
let mut headers = http::HeaderMap::new();
headers.append(
http::header::ACCEPT_ENCODING,
http::HeaderValue::from_static("deflate,x-gzip"),
);
let encoding = Encoding::from_headers(&headers, SupportedEncodingsAll);
assert_eq!(Encoding::Gzip, encoding);
}

#[test]
fn accept_encoding_header_three_encodings() {
let mut headers = http::HeaderMap::new();
Expand Down

0 comments on commit e0192a3

Please sign in to comment.