1
0
mirror of https://github.com/fafhrd91/actix-web synced 2024-11-30 18:44:35 +01:00

migrate to brotli crate (#2538)

This commit is contained in:
Rob Ede 2022-01-15 14:03:16 +00:00 committed by GitHub
parent 455d5c460d
commit e7cae5a95b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 40 additions and 26 deletions

View File

@ -109,7 +109,7 @@ actix-files = "0.6.0-beta.14"
actix-test = { version = "0.1.0-beta.11", features = ["openssl", "rustls"] } actix-test = { version = "0.1.0-beta.11", features = ["openssl", "rustls"] }
awc = { version = "3.0.0-beta.18", features = ["openssl"] } awc = { version = "3.0.0-beta.18", features = ["openssl"] }
brotli2 = "0.3.2" brotli = "3.3.3"
const-str = "0.3" const-str = "0.3"
criterion = { version = "0.3", features = ["html_reports"] } criterion = { version = "0.3", features = ["html_reports"] }
env_logger = "0.9" env_logger = "0.9"

View File

@ -33,7 +33,7 @@ openssl = ["actix-tls/accept", "actix-tls/openssl"]
rustls = ["actix-tls/accept", "actix-tls/rustls"] rustls = ["actix-tls/accept", "actix-tls/rustls"]
# enable compression support # enable compression support
compress-brotli = ["brotli2", "__compress"] compress-brotli = ["brotli", "__compress"]
compress-gzip = ["flate2", "__compress"] compress-gzip = ["flate2", "__compress"]
compress-zstd = ["zstd", "__compress"] compress-zstd = ["zstd", "__compress"]
@ -74,7 +74,7 @@ smallvec = "1.6.1"
actix-tls = { version = "3.0.0", default-features = false, optional = true } actix-tls = { version = "3.0.0", default-features = false, optional = true }
# compression # compression
brotli2 = { version="0.3.2", optional = true } brotli = { version = "3.3.3", optional = true }
flate2 = { version = "1.0.13", optional = true } flate2 = { version = "1.0.13", optional = true }
zstd = { version = "0.9", optional = true } zstd = { version = "0.9", optional = true }

View File

@ -11,9 +11,6 @@ use actix_rt::task::{spawn_blocking, JoinHandle};
use bytes::Bytes; use bytes::Bytes;
use futures_core::{ready, Stream}; use futures_core::{ready, Stream};
#[cfg(feature = "compress-brotli")]
use brotli2::write::BrotliDecoder;
#[cfg(feature = "compress-gzip")] #[cfg(feature = "compress-gzip")]
use flate2::write::{GzDecoder, ZlibDecoder}; use flate2::write::{GzDecoder, ZlibDecoder};
@ -48,7 +45,7 @@ where
let decoder = match encoding { let decoder = match encoding {
#[cfg(feature = "compress-brotli")] #[cfg(feature = "compress-brotli")]
ContentEncoding::Brotli => Some(ContentDecoder::Brotli(Box::new( ContentEncoding::Brotli => Some(ContentDecoder::Brotli(Box::new(
BrotliDecoder::new(Writer::new()), brotli::DecompressorWriter::new(Writer::new(), 8_096),
))), ))),
#[cfg(feature = "compress-gzip")] #[cfg(feature = "compress-gzip")]
ContentEncoding::Deflate => Some(ContentDecoder::Deflate(Box::new( ContentEncoding::Deflate => Some(ContentDecoder::Deflate(Box::new(
@ -165,7 +162,7 @@ enum ContentDecoder {
#[cfg(feature = "compress-gzip")] #[cfg(feature = "compress-gzip")]
Gzip(Box<GzDecoder<Writer>>), Gzip(Box<GzDecoder<Writer>>),
#[cfg(feature = "compress-brotli")] #[cfg(feature = "compress-brotli")]
Brotli(Box<BrotliDecoder<Writer>>), Brotli(Box<brotli::DecompressorWriter<Writer>>),
// We need explicit 'static lifetime here because ZstdDecoder need lifetime // We need explicit 'static lifetime here because ZstdDecoder need lifetime
// argument, and we use `spawn_blocking` in `Decoder::poll_next` that require `FnOnce() -> R + Send + 'static` // argument, and we use `spawn_blocking` in `Decoder::poll_next` that require `FnOnce() -> R + Send + 'static`
#[cfg(feature = "compress-zstd")] #[cfg(feature = "compress-zstd")]

View File

@ -14,9 +14,6 @@ use derive_more::Display;
use futures_core::ready; use futures_core::ready;
use pin_project_lite::pin_project; use pin_project_lite::pin_project;
#[cfg(feature = "compress-brotli")]
use brotli2::write::BrotliEncoder;
#[cfg(feature = "compress-gzip")] #[cfg(feature = "compress-gzip")]
use flate2::write::{GzEncoder, ZlibEncoder}; use flate2::write::{GzEncoder, ZlibEncoder};
@ -268,7 +265,7 @@ enum ContentEncoder {
Gzip(GzEncoder<Writer>), Gzip(GzEncoder<Writer>),
#[cfg(feature = "compress-brotli")] #[cfg(feature = "compress-brotli")]
Brotli(BrotliEncoder<Writer>), Brotli(Box<brotli::CompressorWriter<Writer>>),
// Wwe need explicit 'static lifetime here because ZstdEncoder needs a lifetime argument and we // Wwe need explicit 'static lifetime here because ZstdEncoder needs a lifetime argument and we
// use `spawn_blocking` in `Encoder::poll_next` that requires `FnOnce() -> R + Send + 'static`. // use `spawn_blocking` in `Encoder::poll_next` that requires `FnOnce() -> R + Send + 'static`.
@ -292,9 +289,7 @@ impl ContentEncoder {
))), ))),
#[cfg(feature = "compress-brotli")] #[cfg(feature = "compress-brotli")]
ContentEncoding::Brotli => { ContentEncoding::Brotli => Some(ContentEncoder::Brotli(new_brotli_compressor())),
Some(ContentEncoder::Brotli(BrotliEncoder::new(Writer::new(), 3)))
}
#[cfg(feature = "compress-zstd")] #[cfg(feature = "compress-zstd")]
ContentEncoding::Zstd => { ContentEncoding::Zstd => {
@ -326,8 +321,8 @@ impl ContentEncoder {
fn finish(self) -> Result<Bytes, io::Error> { fn finish(self) -> Result<Bytes, io::Error> {
match self { match self {
#[cfg(feature = "compress-brotli")] #[cfg(feature = "compress-brotli")]
ContentEncoder::Brotli(encoder) => match encoder.finish() { ContentEncoder::Brotli(mut encoder) => match encoder.flush() {
Ok(writer) => Ok(writer.buf.freeze()), Ok(()) => Ok(encoder.into_inner().buf.freeze()),
Err(err) => Err(err), Err(err) => Err(err),
}, },
@ -392,6 +387,16 @@ impl ContentEncoder {
} }
} }
#[cfg(feature = "compress-brotli")]
fn new_brotli_compressor() -> Box<brotli::CompressorWriter<Writer>> {
Box::new(brotli::CompressorWriter::new(
Writer::new(),
8 * 1024, // 32 KiB buffer
3, // BROTLI_PARAM_QUALITY
22, // BROTLI_PARAM_LGWIN
))
}
#[derive(Debug, Display)] #[derive(Debug, Display)]
#[non_exhaustive] #[non_exhaustive]
pub enum EncoderError { pub enum EncoderError {

View File

@ -101,7 +101,7 @@ actix-tls = { version = "3.0.0", features = ["openssl", "rustls"] }
actix-utils = "3.0.0" actix-utils = "3.0.0"
actix-web = { version = "4.0.0-beta.20", features = ["openssl"] } actix-web = { version = "4.0.0-beta.20", features = ["openssl"] }
brotli2 = "0.3.2" brotli = "3.3.3"
const-str = "0.3" const-str = "0.3"
env_logger = "0.9" env_logger = "0.9"
flate2 = "1.0.13" flate2 = "1.0.13"

View File

@ -41,16 +41,22 @@ pub mod deflate {
pub mod brotli { pub mod brotli {
use super::*; use super::*;
use ::brotli2::{read::BrotliDecoder, write::BrotliEncoder}; use ::brotli::{reader::Decompressor as BrotliDecoder, CompressorWriter as BrotliEncoder};
pub fn encode(bytes: impl AsRef<[u8]>) -> Vec<u8> { pub fn encode(bytes: impl AsRef<[u8]>) -> Vec<u8> {
let mut encoder = BrotliEncoder::new(Vec::new(), 3); let mut encoder = BrotliEncoder::new(
Vec::new(),
8 * 1024, // 32 KiB buffer
3, // BROTLI_PARAM_QUALITY
22, // BROTLI_PARAM_LGWIN
);
encoder.write_all(bytes.as_ref()).unwrap(); encoder.write_all(bytes.as_ref()).unwrap();
encoder.finish().unwrap() encoder.flush().unwrap();
encoder.into_inner()
} }
pub fn decode(bytes: impl AsRef<[u8]>) -> Vec<u8> { pub fn decode(bytes: impl AsRef<[u8]>) -> Vec<u8> {
let mut decoder = BrotliDecoder::new(bytes.as_ref()); let mut decoder = BrotliDecoder::new(bytes.as_ref(), 8_096);
let mut buf = Vec::new(); let mut buf = Vec::new();
decoder.read_to_end(&mut buf).unwrap(); decoder.read_to_end(&mut buf).unwrap();
buf buf

View File

@ -41,16 +41,22 @@ pub mod deflate {
pub mod brotli { pub mod brotli {
use super::*; use super::*;
use ::brotli2::{read::BrotliDecoder, write::BrotliEncoder}; use ::brotli::{reader::Decompressor as BrotliDecoder, CompressorWriter as BrotliEncoder};
pub fn encode(bytes: impl AsRef<[u8]>) -> Vec<u8> { pub fn encode(bytes: impl AsRef<[u8]>) -> Vec<u8> {
let mut encoder = BrotliEncoder::new(Vec::new(), 3); let mut encoder = BrotliEncoder::new(
Vec::new(),
8 * 1024, // 32 KiB buffer
3, // BROTLI_PARAM_QUALITY
22, // BROTLI_PARAM_LGWIN
);
encoder.write_all(bytes.as_ref()).unwrap(); encoder.write_all(bytes.as_ref()).unwrap();
encoder.finish().unwrap() encoder.flush().unwrap();
encoder.into_inner()
} }
pub fn decode(bytes: impl AsRef<[u8]>) -> Vec<u8> { pub fn decode(bytes: impl AsRef<[u8]>) -> Vec<u8> {
let mut decoder = BrotliDecoder::new(bytes.as_ref()); let mut decoder = BrotliDecoder::new(bytes.as_ref(), 8_096);
let mut buf = Vec::new(); let mut buf = Vec::new();
decoder.read_to_end(&mut buf).unwrap(); decoder.read_to_end(&mut buf).unwrap();
buf buf