Skip to content

Commit

Permalink
Merge pull request #131 from jirutka/fix-zlib
Browse files Browse the repository at this point in the history
Fix compress-zlib and compress-zlib-ng to actually enable compression
  • Loading branch information
sbstp authored Oct 9, 2022
2 parents 8b4f2fc + 1be4636 commit 20b765b
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 38 deletions.
8 changes: 5 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,14 @@ tokio-stream = {version = "0.1.9", features = ["net"]}
warp = "0.3.2"

[features]
# This is not a real user-facing feature, don't enable it directly.
_compress-any = []
basic-auth = ["base64"]
charsets = ["encoding_rs", "encoding_rs_io"]
# The following three compress features are mutually exclusive.
compress = ["flate2/default"]
compress-zlib = ["flate2/zlib"]
compress-zlib-ng = ["flate2/zlib-ng"]
compress = ["flate2/default", "_compress-any"]
compress-zlib = ["flate2/zlib", "_compress-any"]
compress-zlib-ng = ["flate2/zlib-ng", "_compress-any"]
default = ["compress", "tls"]
form = ["serde", "serde_urlencoded"]
json = ["serde", "serde_json"]
Expand Down
50 changes: 25 additions & 25 deletions src/parsing/compressed_reader.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use std::io::{self, Read};

#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
use flate2::bufread::{DeflateDecoder, GzDecoder};
use http::header::HeaderMap;
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
use http::header::{CONTENT_ENCODING, TRANSFER_ENCODING};
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
use http::Method;

use crate::error::Result;
Expand All @@ -16,18 +16,18 @@ use crate::request::PreparedRequest;
#[derive(Debug)]
pub enum CompressedReader {
Plain(BodyReader),
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
Deflate(DeflateDecoder<BodyReader>),
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
Gzip(GzDecoder<BodyReader>),
}

#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
fn have_encoding_item(value: &str, enc: &str) -> bool {
value.split(',').map(|s| s.trim()).any(|s| s.eq_ignore_ascii_case(enc))
}

#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
fn have_encoding_content_encoding(headers: &HeaderMap, enc: &str) -> bool {
headers
.get_all(CONTENT_ENCODING)
Expand All @@ -36,7 +36,7 @@ fn have_encoding_content_encoding(headers: &HeaderMap, enc: &str) -> bool {
.any(|val| have_encoding_item(val, enc))
}

#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
fn have_encoding_transfer_encoding(headers: &HeaderMap, enc: &str) -> bool {
headers
.get_all(TRANSFER_ENCODING)
Expand All @@ -45,13 +45,13 @@ fn have_encoding_transfer_encoding(headers: &HeaderMap, enc: &str) -> bool {
.any(|val| have_encoding_item(val, enc))
}

#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
fn have_encoding(headers: &HeaderMap, enc: &str) -> bool {
have_encoding_content_encoding(headers, enc) || have_encoding_transfer_encoding(headers, enc)
}

impl CompressedReader {
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
pub fn new<B>(headers: &HeaderMap, request: &PreparedRequest<B>, reader: BodyReader) -> Result<CompressedReader> {
if request.method() != Method::HEAD {
if have_encoding(headers, "gzip") {
Expand All @@ -68,7 +68,7 @@ impl CompressedReader {
Ok(CompressedReader::Plain(reader))
}

#[cfg(not(feature = "compress"))]
#[cfg(not(feature = "_compress-any"))]
pub fn new<B>(_: &HeaderMap, _: &PreparedRequest<B>, reader: BodyReader) -> Result<CompressedReader> {
Ok(CompressedReader::Plain(reader))
}
Expand All @@ -80,9 +80,9 @@ impl Read for CompressedReader {
// TODO: gzip does not read until EOF, leaving some data in the buffer.
match self {
CompressedReader::Plain(s) => s.read(buf),
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
CompressedReader::Deflate(s) => s.read(buf),
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
CompressedReader::Gzip(s) => s.read(buf),
}
}
Expand All @@ -92,55 +92,55 @@ impl Read for CompressedReader {
mod tests {
use std::io::prelude::*;

#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
use flate2::{
write::{DeflateEncoder, GzEncoder},
Compression,
};
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
use http::header::{HeaderMap, HeaderValue};
use http::Method;

#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
use super::have_encoding;
use crate::parsing::response::parse_response;
use crate::streams::BaseStream;
use crate::PreparedRequest;

#[test]
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
fn test_have_encoding_none() {
let mut headers = HeaderMap::new();
headers.insert("content-encoding", HeaderValue::from_static("gzip"));
assert!(!have_encoding(&headers, "deflate"));
}

#[test]
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
fn test_have_encoding_content_encoding_simple() {
let mut headers = HeaderMap::new();
headers.insert("content-encoding", HeaderValue::from_static("gzip"));
assert!(have_encoding(&headers, "gzip"));
}

#[test]
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
fn test_have_encoding_content_encoding_multi() {
let mut headers = HeaderMap::new();
headers.insert("content-encoding", HeaderValue::from_static("identity, deflate"));
assert!(have_encoding(&headers, "deflate"));
}

#[test]
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
fn test_have_encoding_transfer_encoding_simple() {
let mut headers = HeaderMap::new();
headers.insert("transfer-encoding", HeaderValue::from_static("deflate"));
assert!(have_encoding(&headers, "deflate"));
}

#[test]
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
fn test_have_encoding_transfer_encoding_multi() {
let mut headers = HeaderMap::new();
headers.insert("transfer-encoding", HeaderValue::from_static("gzip, chunked"));
Expand All @@ -163,7 +163,7 @@ mod tests {
}

#[test]
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
fn test_stream_deflate() {
let mut payload = Vec::new();
let mut enc = DeflateEncoder::new(&mut payload, Compression::default());
Expand All @@ -186,7 +186,7 @@ mod tests {
}

#[test]
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
fn test_stream_gzip() {
let mut payload = Vec::new();
let mut enc = GzEncoder::new(&mut payload, Compression::default());
Expand All @@ -210,7 +210,7 @@ mod tests {
}

#[test]
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
fn test_no_body_with_gzip() {
let buf = b"HTTP/1.1 200 OK\r\ncontent-encoding: gzip\r\n\r\n";

Expand All @@ -221,7 +221,7 @@ mod tests {
}

#[test]
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
fn test_no_body_with_gzip_head() {
let buf = b"HTTP/1.1 200 OK\r\ncontent-encoding: gzip\r\n\r\n";

Expand Down
8 changes: 4 additions & 4 deletions src/request/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ impl<B> RequestBuilder<B> {
///
/// This value defaults to true. Note that this only lets the browser know that this request supports
/// compression, the server might choose not to compress the content.
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
pub fn allow_compression(mut self, allow_compression: bool) -> Self {
self.base_settings.allow_compression = allow_compression;
self
Expand Down Expand Up @@ -579,7 +579,7 @@ mod tests {
}
}

#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
fn assert_request_content(
builder: RequestBuilder,
status_line: &str,
Expand Down Expand Up @@ -615,7 +615,7 @@ mod tests {
}

#[test]
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
fn test_request_builder_write_request_no_query() {
assert_request_content(
RequestBuilder::new(Method::GET, "http://localhost:1337/foo"),
Expand All @@ -631,7 +631,7 @@ mod tests {
}

#[test]
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
fn test_request_builder_write_request_with_query() {
assert_request_content(
RequestBuilder::new(Method::GET, "http://localhost:1337/foo").param("hello", "world"),
Expand Down
6 changes: 3 additions & 3 deletions src/request/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::io::{prelude::*, BufWriter};
use std::str;
use std::time::Instant;

#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
use http::header::ACCEPT_ENCODING;
use http::{
header::{HeaderValue, IntoHeaderName, HOST},
Expand Down Expand Up @@ -85,12 +85,12 @@ impl PreparedRequest<body::Empty> {
}

impl<B> PreparedRequest<B> {
#[cfg(not(feature = "compress"))]
#[cfg(not(feature = "_compress-any"))]
fn set_compression(&mut self) -> Result {
Ok(())
}

#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
fn set_compression(&mut self) -> Result {
if self.base_settings.allow_compression {
header_insert(&mut self.base_settings.headers, ACCEPT_ENCODING, "gzip, deflate")?;
Expand Down
2 changes: 1 addition & 1 deletion src/request/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ impl Session {
///
/// This value defaults to true. Note that this only lets the browser know that this `Request` supports
/// compression, the server might choose not to compress the content.
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
pub fn allow_compression(&mut self, allow_compression: bool) {
self.base_settings.allow_compression = allow_compression;
}
Expand Down
4 changes: 2 additions & 2 deletions src/request/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub struct BaseSettings {

#[cfg(feature = "charsets")]
pub default_charset: Option<Charset>,
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
pub allow_compression: bool,
}

Expand All @@ -45,7 +45,7 @@ impl Default for BaseSettings {

#[cfg(feature = "charsets")]
default_charset: None,
#[cfg(feature = "compress")]
#[cfg(feature = "_compress-any")]
allow_compression: true,
}
}
Expand Down

0 comments on commit 20b765b

Please sign in to comment.