diff --git a/Cargo.toml b/Cargo.toml index 563642105..e6c241f8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -76,7 +76,7 @@ lazy_static = "1.0" url = { version="1.7", features=["query_encoding"] } cookie = { version="0.10", features=["percent-encode"] } brotli2 = { version="^0.3.2", optional = true } -flate2 = { version="1.0", default-features = false } +flate2 = { version="1.0", optional = true, default-features = false } # io mio = "^0.6.13" diff --git a/src/client/writer.rs b/src/client/writer.rs index 48e4cc711..36c9d6ee0 100644 --- a/src/client/writer.rs +++ b/src/client/writer.rs @@ -7,8 +7,10 @@ use std::io::{self, Write}; #[cfg(feature = "brotli")] use brotli2::write::BrotliEncoder; use bytes::{BufMut, BytesMut}; -use flate2::Compression; +#[cfg(feature = "flate2")] use flate2::write::{DeflateEncoder, GzEncoder}; +#[cfg(feature = "flate2")] +use flate2::Compression; use futures::{Async, Poll}; use http::header::{HeaderValue, CONNECTION, CONTENT_ENCODING, CONTENT_LENGTH, DATE, TRANSFER_ENCODING}; @@ -18,9 +20,9 @@ use tokio_io::AsyncWrite; use body::{Binary, Body}; use header::ContentEncoding; -use server::WriterState; use server::encoding::{ContentEncoder, TransferEncoding}; use server::shared::SharedBytes; +use server::WriterState; use client::ClientRequest; @@ -70,7 +72,7 @@ impl HttpClientWriter { // !self.flags.contains(Flags::UPGRADE) } fn write_to_stream( - &mut self, stream: &mut T + &mut self, stream: &mut T, ) -> io::Result { while !self.buffer.is_empty() { match stream.write(self.buffer.as_ref()) { @@ -191,7 +193,7 @@ impl HttpClientWriter { #[inline] pub fn poll_completed( - &mut self, stream: &mut T, shutdown: bool + &mut self, stream: &mut T, shutdown: bool, ) -> Poll<(), io::Error> { match self.write_to_stream(stream) { Ok(WriterState::Done) => { @@ -222,9 +224,11 @@ fn content_encoder(buf: SharedBytes, req: &mut ClientRequest) -> ContentEncoder let tmp = SharedBytes::default(); let transfer = TransferEncoding::eof(tmp.clone()); let mut enc = match encoding { + #[cfg(feature = "flate2")] ContentEncoding::Deflate => ContentEncoder::Deflate( DeflateEncoder::new(transfer, Compression::default()), ), + #[cfg(feature = "flate2")] ContentEncoding::Gzip => ContentEncoder::Gzip(GzEncoder::new( transfer, Compression::default(), @@ -283,10 +287,12 @@ fn content_encoder(buf: SharedBytes, req: &mut ClientRequest) -> ContentEncoder req.replace_body(body); match encoding { + #[cfg(feature = "flate2")] ContentEncoding::Deflate => ContentEncoder::Deflate(DeflateEncoder::new( transfer, Compression::default(), )), + #[cfg(feature = "flate2")] ContentEncoding::Gzip => { ContentEncoder::Gzip(GzEncoder::new(transfer, Compression::default())) } @@ -299,7 +305,7 @@ fn content_encoder(buf: SharedBytes, req: &mut ClientRequest) -> ContentEncoder } fn streaming_encoding( - buf: SharedBytes, version: Version, req: &mut ClientRequest + buf: SharedBytes, version: Version, req: &mut ClientRequest, ) -> TransferEncoding { if req.chunked() { // Enable transfer encoding diff --git a/src/header/mod.rs b/src/header/mod.rs index 3564da9e2..7d791c7b8 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -6,8 +6,8 @@ use std::str::FromStr; use bytes::{Bytes, BytesMut}; use mime::Mime; -use modhttp::Error as HttpError; use modhttp::header::GetAll; +use modhttp::Error as HttpError; pub use modhttp::header::*; @@ -116,8 +116,10 @@ pub enum ContentEncoding { #[cfg(feature = "brotli")] Br, /// A format using the zlib structure with deflate algorithm + #[cfg(feature = "flate2")] Deflate, /// Gzip algorithm + #[cfg(feature = "flate2")] Gzip, /// Indicates the identity function (i.e. no compression, nor modification) Identity, @@ -137,7 +139,9 @@ impl ContentEncoding { match *self { #[cfg(feature = "brotli")] ContentEncoding::Br => "br", + #[cfg(feature = "flate2")] ContentEncoding::Gzip => "gzip", + #[cfg(feature = "flate2")] ContentEncoding::Deflate => "deflate", ContentEncoding::Identity | ContentEncoding::Auto => "identity", } @@ -149,7 +153,9 @@ impl ContentEncoding { match *self { #[cfg(feature = "brotli")] ContentEncoding::Br => 1.1, + #[cfg(feature = "flate2")] ContentEncoding::Gzip => 1.0, + #[cfg(feature = "flate2")] ContentEncoding::Deflate => 0.9, ContentEncoding::Identity | ContentEncoding::Auto => 0.1, } @@ -159,10 +165,12 @@ impl ContentEncoding { // TODO: remove memory allocation impl<'a> From<&'a str> for ContentEncoding { fn from(s: &'a str) -> ContentEncoding { - match s.trim().to_lowercase().as_ref() { + match AsRef::::as_ref(&s.trim().to_lowercase()) { #[cfg(feature = "brotli")] "br" => ContentEncoding::Br, + #[cfg(feature = "flate2")] "gzip" => ContentEncoding::Gzip, + #[cfg(feature = "flate2")] "deflate" => ContentEncoding::Deflate, _ => ContentEncoding::Identity, } @@ -202,7 +210,7 @@ impl fmt::Write for Writer { #[doc(hidden)] /// Reads a comma-delimited raw header into a Vec. pub fn from_comma_delimited( - all: GetAll + all: GetAll, ) -> Result, ParseError> { let mut result = Vec::new(); for h in all { diff --git a/src/lib.rs b/src/lib.rs index 1a0ac8ade..2efac129e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,8 +64,10 @@ #![cfg_attr(actix_nightly, feature( specialization, // for impl ErrorResponse for std::error::Error ))] -#![cfg_attr(feature = "cargo-clippy", - allow(decimal_literal_representation, suspicious_arithmetic_impl))] +#![cfg_attr( + feature = "cargo-clippy", + allow(decimal_literal_representation, suspicious_arithmetic_impl) +)] #[macro_use] extern crate log; @@ -103,6 +105,7 @@ extern crate serde; #[cfg(feature = "brotli")] extern crate brotli2; extern crate encoding; +#[cfg(feature = "flate2")] extern crate flate2; extern crate h2 as http2; extern crate num_cpus; diff --git a/src/server/encoding.rs b/src/server/encoding.rs index 7c886fe5c..ae69ae07f 100644 --- a/src/server/encoding.rs +++ b/src/server/encoding.rs @@ -6,11 +6,14 @@ use std::{cmp, io, mem}; #[cfg(feature = "brotli")] use brotli2::write::{BrotliDecoder, BrotliEncoder}; use bytes::{BufMut, Bytes, BytesMut}; -use flate2::Compression; +#[cfg(feature = "flate2")] use flate2::read::GzDecoder; +#[cfg(feature = "flate2")] use flate2::write::{DeflateDecoder, DeflateEncoder, GzEncoder}; -use http::header::{HeaderMap, HeaderValue, ACCEPT_ENCODING, - CONTENT_ENCODING, CONTENT_LENGTH, TRANSFER_ENCODING}; +#[cfg(feature = "flate2")] +use flate2::Compression; +use http::header::{HeaderMap, HeaderValue, ACCEPT_ENCODING, CONTENT_ENCODING, + CONTENT_LENGTH, TRANSFER_ENCODING}; use http::{HttpTryFrom, Method, Version}; use body::{Binary, Body}; @@ -144,7 +147,9 @@ impl PayloadWriter for EncodedPayload { } pub(crate) enum Decoder { + #[cfg(feature = "flate2")] Deflate(Box>), + #[cfg(feature = "flate2")] Gzip(Option>>), #[cfg(feature = "brotli")] Br(Box>), @@ -223,9 +228,11 @@ impl PayloadStream { ContentEncoding::Br => { Decoder::Br(Box::new(BrotliDecoder::new(Writer::new()))) } + #[cfg(feature = "flate2")] ContentEncoding::Deflate => { Decoder::Deflate(Box::new(DeflateDecoder::new(Writer::new()))) } + #[cfg(feature = "flate2")] ContentEncoding::Gzip => Decoder::Gzip(None), _ => Decoder::Identity, }; @@ -251,6 +258,7 @@ impl PayloadStream { } Err(e) => Err(e), }, + #[cfg(feature = "flate2")] Decoder::Gzip(ref mut decoder) => { if let Some(ref mut decoder) = *decoder { decoder.as_mut().get_mut().eof = true; @@ -267,6 +275,7 @@ impl PayloadStream { Ok(None) } } + #[cfg(feature = "flate2")] Decoder::Deflate(ref mut decoder) => match decoder.try_finish() { Ok(_) => { let b = decoder.get_mut().take(); @@ -297,6 +306,7 @@ impl PayloadStream { } Err(e) => Err(e), }, + #[cfg(feature = "flate2")] Decoder::Gzip(ref mut decoder) => { if decoder.is_none() { *decoder = Some(Box::new(GzDecoder::new(Wrapper { @@ -334,6 +344,7 @@ impl PayloadStream { } } } + #[cfg(feature = "flate2")] Decoder::Deflate(ref mut decoder) => match decoder.write_all(&data) { Ok(_) => { decoder.flush()?; @@ -352,7 +363,9 @@ impl PayloadStream { } pub(crate) enum ContentEncoder { + #[cfg(feature = "flate2")] Deflate(DeflateEncoder), + #[cfg(feature = "flate2")] Gzip(GzEncoder), #[cfg(feature = "brotli")] Br(BrotliEncoder), @@ -422,9 +435,11 @@ impl ContentEncoder { let tmp = SharedBytes::default(); let transfer = TransferEncoding::eof(tmp.clone()); let mut enc = match encoding { + #[cfg(feature = "flate2")] ContentEncoding::Deflate => ContentEncoder::Deflate( DeflateEncoder::new(transfer, Compression::fast()), ), + #[cfg(feature = "flate2")] ContentEncoding::Gzip => ContentEncoder::Gzip(GzEncoder::new( transfer, Compression::fast(), @@ -478,10 +493,12 @@ impl ContentEncoder { } match encoding { + #[cfg(feature = "flate2")] ContentEncoding::Deflate => ContentEncoder::Deflate(DeflateEncoder::new( transfer, Compression::fast(), )), + #[cfg(feature = "flate2")] ContentEncoding::Gzip => { ContentEncoder::Gzip(GzEncoder::new(transfer, Compression::fast())) } @@ -494,7 +511,7 @@ impl ContentEncoder { } fn streaming_encoding( - buf: SharedBytes, version: Version, resp: &mut HttpResponse + buf: SharedBytes, version: Version, resp: &mut HttpResponse, ) -> TransferEncoding { match resp.chunked() { Some(true) => { @@ -563,7 +580,9 @@ impl ContentEncoder { match *self { #[cfg(feature = "brotli")] ContentEncoder::Br(ref encoder) => encoder.get_ref().is_eof(), + #[cfg(feature = "flate2")] ContentEncoder::Deflate(ref encoder) => encoder.get_ref().is_eof(), + #[cfg(feature = "flate2")] ContentEncoder::Gzip(ref encoder) => encoder.get_ref().is_eof(), ContentEncoder::Identity(ref encoder) => encoder.is_eof(), } @@ -587,6 +606,7 @@ impl ContentEncoder { } Err(err) => Err(err), }, + #[cfg(feature = "flate2")] ContentEncoder::Gzip(encoder) => match encoder.finish() { Ok(mut writer) => { writer.encode_eof(); @@ -595,6 +615,7 @@ impl ContentEncoder { } Err(err) => Err(err), }, + #[cfg(feature = "flate2")] ContentEncoder::Deflate(encoder) => match encoder.finish() { Ok(mut writer) => { writer.encode_eof(); @@ -625,6 +646,7 @@ impl ContentEncoder { } } } + #[cfg(feature = "flate2")] ContentEncoder::Gzip(ref mut encoder) => { match encoder.write_all(data.as_ref()) { Ok(_) => Ok(()), @@ -634,6 +656,7 @@ impl ContentEncoder { } } } + #[cfg(feature = "flate2")] ContentEncoder::Deflate(ref mut encoder) => { match encoder.write_all(data.as_ref()) { Ok(_) => Ok(()),