diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 828d62561..a4b54ca7a 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -1,8 +1,6 @@ name: Benchmark on: - pull_request: - types: [opened, synchronize, reopened] push: branches: - master diff --git a/actix-http/src/encoding/encoder.rs b/actix-http/src/encoding/encoder.rs index 8072f79cc..140126ff8 100644 --- a/actix-http/src/encoding/encoder.rs +++ b/actix-http/src/encoding/encoder.rs @@ -299,7 +299,7 @@ impl ContentEncoder { Some(ContentEncoder::Zstd(encoder)) } - _ => None, + ContentEncoding::Identity => None, } } diff --git a/src/types/payload.rs b/src/types/payload.rs index 73987def5..d2ab29639 100644 --- a/src/types/payload.rs +++ b/src/types/payload.rs @@ -248,6 +248,7 @@ impl PayloadConfig { } } } + Ok(()) } diff --git a/tests/compression.rs b/tests/compression.rs index 40b9c40a1..71e3ecf50 100644 --- a/tests/compression.rs +++ b/tests/compression.rs @@ -7,6 +7,9 @@ use actix_web::{ }; use bytes::Bytes; +mod test_utils; +use test_utils::{brotli, gzip, zstd}; + static LOREM: &[u8] = include_bytes!("fixtures/lorem.txt"); static LOREM_GZIP: &[u8] = include_bytes!("fixtures/lorem.txt.gz"); static LOREM_BR: &[u8] = include_bytes!("fixtures/lorem.txt.br"); @@ -106,6 +109,16 @@ async fn negotiate_encoding_gzip() { let bytes = res.body().await.unwrap(); assert_eq!(bytes, Bytes::from_static(LOREM)); + let mut res = srv + .post("/static") + .no_decompress() + .insert_header((header::ACCEPT_ENCODING, "gzip,br,zstd")) + .send() + .await + .unwrap(); + let bytes = res.body().await.unwrap(); + assert_eq!(gzip::decode(bytes), LOREM); + srv.stop().await; } @@ -125,6 +138,16 @@ async fn negotiate_encoding_br() { let bytes = res.body().await.unwrap(); assert_eq!(bytes, Bytes::from_static(LOREM)); + let mut res = srv + .post("/static") + .no_decompress() + .insert_header((header::ACCEPT_ENCODING, "br,zstd,gzip")) + .send() + .await + .unwrap(); + let bytes = res.body().await.unwrap(); + assert_eq!(brotli::decode(bytes), LOREM); + srv.stop().await; } @@ -144,6 +167,16 @@ async fn negotiate_encoding_zstd() { let bytes = res.body().await.unwrap(); assert_eq!(bytes, Bytes::from_static(LOREM)); + let mut res = srv + .post("/static") + .no_decompress() + .insert_header((header::ACCEPT_ENCODING, "zstd,gzip,br")) + .send() + .await + .unwrap(); + let bytes = res.body().await.unwrap(); + assert_eq!(zstd::decode(bytes), LOREM); + srv.stop().await; } @@ -261,7 +294,7 @@ async fn deny_identity_for_manual_coding() { let srv = test_server!(); let req = srv - .post("/static") + .post("/static-xz") // don't decompress response body .no_decompress() // signal that we want a compressed body diff --git a/tests/test_server.rs b/tests/test_server.rs index ae047e31b..287f27dfa 100644 --- a/tests/test_server.rs +++ b/tests/test_server.rs @@ -11,30 +11,28 @@ use std::{ }; use actix_web::{ + cookie::{Cookie, CookieBuilder}, dev::BodyEncoding, - http::header::{ - ContentEncoding, ACCEPT_ENCODING, CONTENT_ENCODING, CONTENT_LENGTH, TRANSFER_ENCODING, + http::{ + header::{self, ContentEncoding, ACCEPT_ENCODING, CONTENT_ENCODING, TRANSFER_ENCODING}, + StatusCode, }, middleware::{Compress, NormalizePath, TrailingSlash}, web, App, Error, HttpResponse, }; -use brotli2::write::{BrotliDecoder, BrotliEncoder}; use bytes::Bytes; -use cookie::{Cookie, CookieBuilder}; -use flate2::{ - read::GzDecoder, - write::{GzEncoder, ZlibDecoder, ZlibEncoder}, - Compression, -}; use futures_core::ready; +use rand::{distributions::Alphanumeric, Rng as _}; + #[cfg(feature = "openssl")] use openssl::{ pkey::PKey, ssl::{SslAcceptor, SslMethod}, x509::X509, }; -use rand::{distributions::Alphanumeric, Rng}; -use zstd::stream::{read::Decoder as ZstdDecoder, write::Encoder as ZstdEncoder}; + +mod test_utils; +use test_utils::{brotli, deflate, gzip, zstd}; const STR: &str = "Hello World Hello World Hello World Hello World Hello World \ Hello World Hello World Hello World Hello World Hello World \ @@ -122,74 +120,15 @@ async fn test_body() { App::new().service(web::resource("/").route(web::to(|| HttpResponse::Ok().body(STR)))) }); - let mut response = srv.get("/").send().await.unwrap(); - assert!(response.status().is_success()); + let mut res = srv.get("/").send().await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); + let bytes = res.body().await.unwrap(); assert_eq!(bytes, Bytes::from_static(STR.as_ref())); srv.stop().await; } -#[actix_rt::test] -async fn test_body_gzip() { - let srv = actix_test::start_with(actix_test::config().h1(), || { - App::new() - .wrap(Compress::new(ContentEncoding::Gzip)) - .service(web::resource("/").route(web::to(|| HttpResponse::Ok().body(STR)))) - }); - - let mut response = srv - .get("/") - .no_decompress() - .append_header((ACCEPT_ENCODING, "gzip")) - .send() - .await - .unwrap(); - assert!(response.status().is_success()); - - // read response - let bytes = response.body().await.unwrap(); - - // decode - let mut e = GzDecoder::new(&bytes[..]); - let mut dec = Vec::new(); - e.read_to_end(&mut dec).unwrap(); - assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref())); - - srv.stop().await; -} - -#[actix_rt::test] -async fn test_body_gzip2() { - let srv = actix_test::start_with(actix_test::config().h1(), || { - App::new() - .wrap(Compress::new(ContentEncoding::Gzip)) - .service(web::resource("/").route(web::to(|| HttpResponse::Ok().body(STR)))) - }); - - let mut response = srv - .get("/") - .no_decompress() - .append_header((ACCEPT_ENCODING, "gzip")) - .send() - .await - .unwrap(); - assert!(response.status().is_success()); - - // read response - let bytes = response.body().await.unwrap(); - - // decode - let mut e = GzDecoder::new(&bytes[..]); - let mut dec = Vec::new(); - e.read_to_end(&mut dec).unwrap(); - assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref())); - - srv.stop().await; -} - #[actix_rt::test] async fn test_body_encoding_override() { let srv = actix_test::start_with(actix_test::config().h1(), || { @@ -201,61 +140,49 @@ async fn test_body_encoding_override() { .body(STR) }))) .service(web::resource("/raw").route(web::to(|| { - let mut response = - HttpResponse::with_body(actix_web::http::StatusCode::OK, STR); - response.encoding(ContentEncoding::Deflate); - response.map_into_boxed_body() + let mut res = HttpResponse::with_body(actix_web::http::StatusCode::OK, STR); + res.encoding(ContentEncoding::Deflate); + res.map_into_boxed_body() }))) }); // Builder - let mut response = srv + let mut res = srv .get("/") .no_decompress() .append_header((ACCEPT_ENCODING, "deflate")) .send() .await .unwrap(); - assert!(response.status().is_success()); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); - - // decode - let mut e = ZlibDecoder::new(Vec::new()); - e.write_all(bytes.as_ref()).unwrap(); - let dec = e.finish().unwrap(); - assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref())); + let bytes = res.body().await.unwrap(); + assert_eq!(deflate::decode(bytes), STR.as_bytes()); // Raw Response - let mut response = srv + let mut res = srv .request(actix_web::http::Method::GET, srv.url("/raw")) .no_decompress() .append_header((ACCEPT_ENCODING, "deflate")) .send() .await .unwrap(); - assert!(response.status().is_success()); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); - - // decode - let mut e = ZlibDecoder::new(Vec::new()); - e.write_all(bytes.as_ref()).unwrap(); - let dec = e.finish().unwrap(); - assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref())); + let bytes = res.body().await.unwrap(); + assert_eq!(deflate::decode(bytes), STR.as_bytes()); srv.stop().await; } #[actix_rt::test] -async fn test_body_gzip_large() { +async fn body_gzip_large() { let data = STR.repeat(10); let srv_data = data.clone(); let srv = actix_test::start_with(actix_test::config().h1(), move || { let data = srv_data.clone(); + App::new() .wrap(Compress::new(ContentEncoding::Gzip)) .service( @@ -264,23 +191,17 @@ async fn test_body_gzip_large() { ) }); - let mut response = srv + let mut res = srv .get("/") .no_decompress() .append_header((ACCEPT_ENCODING, "gzip")) .send() .await .unwrap(); - assert!(response.status().is_success()); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); - - // decode - let mut e = GzDecoder::new(&bytes[..]); - let mut dec = Vec::new(); - e.read_to_end(&mut dec).unwrap(); - assert_eq!(Bytes::from(dec), Bytes::from(data)); + let bytes = res.body().await.unwrap(); + assert_eq!(gzip::decode(bytes), data.as_bytes()); srv.stop().await; } @@ -304,24 +225,17 @@ async fn test_body_gzip_large_random() { ) }); - let mut response = srv + let mut res = srv .get("/") .no_decompress() .append_header((ACCEPT_ENCODING, "gzip")) .send() .await .unwrap(); - assert!(response.status().is_success()); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); - - // decode - let mut e = GzDecoder::new(&bytes[..]); - let mut dec = Vec::new(); - e.read_to_end(&mut dec).unwrap(); - assert_eq!(dec.len(), data.len()); - assert_eq!(Bytes::from(dec), Bytes::from(data)); + let bytes = res.body().await.unwrap(); + assert_eq!(gzip::decode(bytes), data.as_bytes()); srv.stop().await; } @@ -337,27 +251,18 @@ async fn test_body_chunked_implicit() { }))) }); - let mut response = srv + let mut res = srv .get("/") .no_decompress() .append_header((ACCEPT_ENCODING, "gzip")) .send() .await .unwrap(); - assert!(response.status().is_success()); - assert_eq!( - response.headers().get(TRANSFER_ENCODING).unwrap(), - &b"chunked"[..] - ); + assert_eq!(res.status(), StatusCode::OK); + assert_eq!(res.headers().get(TRANSFER_ENCODING).unwrap(), "chunked"); - // read response - let bytes = response.body().await.unwrap(); - - // decode - let mut e = GzDecoder::new(&bytes[..]); - let mut dec = Vec::new(); - e.read_to_end(&mut dec).unwrap(); - assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref())); + let bytes = res.body().await.unwrap(); + assert_eq!(gzip::decode(bytes), STR.as_bytes()); srv.stop().await; } @@ -373,25 +278,17 @@ async fn test_body_br_streaming() { }))) }); - let mut response = srv + let mut res = srv .get("/") .append_header((ACCEPT_ENCODING, "br")) .no_decompress() .send() .await .unwrap(); - assert!(response.status().is_success()); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); - println!("TEST: {:?}", bytes.len()); - - // decode br - let mut e = BrotliDecoder::new(Vec::with_capacity(2048)); - e.write_all(bytes.as_ref()).unwrap(); - let dec = e.finish().unwrap(); - println!("T: {:?}", Bytes::copy_from_slice(&dec)); - assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref())); + let bytes = res.body().await.unwrap(); + assert_eq!(brotli::decode(bytes), STR.as_bytes()); srv.stop().await; } @@ -404,16 +301,13 @@ async fn test_head_binary() { ) }); - let mut response = srv.head("/").send().await.unwrap(); - assert!(response.status().is_success()); + let mut res = srv.head("/").send().await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); - { - let len = response.headers().get(CONTENT_LENGTH).unwrap(); - assert_eq!(format!("{}", STR.len()), len.to_str().unwrap()); - } + let len = res.headers().get(header::CONTENT_LENGTH).unwrap(); + assert_eq!(format!("{}", STR.len()), len.to_str().unwrap()); - // read response - let bytes = response.body().await.unwrap(); + let bytes = res.body().await.unwrap(); assert!(bytes.is_empty()); srv.stop().await; @@ -429,12 +323,11 @@ async fn test_no_chunking() { }))) }); - let mut response = srv.get("/").send().await.unwrap(); - assert!(response.status().is_success()); - assert!(!response.headers().contains_key(TRANSFER_ENCODING)); + let mut res = srv.get("/").send().await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); + assert!(!res.headers().contains_key(TRANSFER_ENCODING)); - // read response - let bytes = response.body().await.unwrap(); + let bytes = res.body().await.unwrap(); assert_eq!(bytes, Bytes::from_static(STR.as_ref())); srv.stop().await; @@ -448,23 +341,17 @@ async fn test_body_deflate() { .service(web::resource("/").route(web::to(move || HttpResponse::Ok().body(STR)))) }); - // client request - let mut response = srv + let mut res = srv .get("/") .append_header((ACCEPT_ENCODING, "deflate")) .no_decompress() .send() .await .unwrap(); - assert!(response.status().is_success()); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); - - let mut e = ZlibDecoder::new(Vec::new()); - e.write_all(bytes.as_ref()).unwrap(); - let dec = e.finish().unwrap(); - assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref())); + let bytes = res.body().await.unwrap(); + assert_eq!(deflate::decode(bytes), STR.as_bytes()); srv.stop().await; } @@ -477,24 +364,17 @@ async fn test_body_brotli() { .service(web::resource("/").route(web::to(move || HttpResponse::Ok().body(STR)))) }); - // client request - let mut response = srv + let mut res = srv .get("/") .append_header((ACCEPT_ENCODING, "br")) .no_decompress() .send() .await .unwrap(); - assert!(response.status().is_success()); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); - - // decode brotli - let mut e = BrotliDecoder::new(Vec::with_capacity(2048)); - e.write_all(bytes.as_ref()).unwrap(); - let dec = e.finish().unwrap(); - assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref())); + let bytes = res.body().await.unwrap(); + assert_eq!(brotli::decode(bytes), STR.as_bytes()); srv.stop().await; } @@ -507,24 +387,17 @@ async fn test_body_zstd() { .service(web::resource("/").route(web::to(move || HttpResponse::Ok().body(STR)))) }); - // client request - let mut response = srv + let mut res = srv .get("/") .append_header((ACCEPT_ENCODING, "zstd")) .no_decompress() .send() .await .unwrap(); - assert!(response.status().is_success()); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); - - // decode - let mut e = ZstdDecoder::new(&bytes[..]).unwrap(); - let mut dec = Vec::new(); - e.read_to_end(&mut dec).unwrap(); - assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref())); + let bytes = res.body().await.unwrap(); + assert_eq!(zstd::decode(bytes), STR.as_bytes()); srv.stop().await; } @@ -540,24 +413,17 @@ async fn test_body_zstd_streaming() { }))) }); - // client request - let mut response = srv + let mut res = srv .get("/") .append_header((ACCEPT_ENCODING, "zstd")) .no_decompress() .send() .await .unwrap(); - assert!(response.status().is_success()); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); - - // decode - let mut e = ZstdDecoder::new(&bytes[..]).unwrap(); - let mut dec = Vec::new(); - e.read_to_end(&mut dec).unwrap(); - assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref())); + let bytes = res.body().await.unwrap(); + assert_eq!(zstd::decode(bytes), STR.as_bytes()); srv.stop().await; } @@ -570,20 +436,14 @@ async fn test_zstd_encoding() { ) }); - let mut e = ZstdEncoder::new(Vec::new(), 5).unwrap(); - e.write_all(STR.as_ref()).unwrap(); - let enc = e.finish().unwrap(); - - // client request let request = srv .post("/") .append_header((CONTENT_ENCODING, "zstd")) - .send_body(enc.clone()); - let mut response = request.await.unwrap(); - assert!(response.status().is_success()); + .send_body(zstd::encode(STR)); + let mut res = request.await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); + let bytes = res.body().await.unwrap(); assert_eq!(bytes, Bytes::from_static(STR.as_ref())); srv.stop().await; @@ -607,21 +467,15 @@ async fn test_zstd_encoding_large() { ) }); - let mut e = ZstdEncoder::new(Vec::new(), 5).unwrap(); - e.write_all(data.as_ref()).unwrap(); - let enc = e.finish().unwrap(); - - // client request let request = srv .post("/") .append_header((CONTENT_ENCODING, "zstd")) - .send_body(enc.clone()); - let mut response = request.await.unwrap(); - assert!(response.status().is_success()); + .send_body(zstd::encode(&data)); + let mut res = request.await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().limit(320_000).await.unwrap(); - assert_eq!(bytes, Bytes::from(data)); + let bytes = res.body().limit(320_000).await.unwrap(); + assert_eq!(bytes, data.as_bytes()); srv.stop().await; } @@ -634,20 +488,14 @@ async fn test_encoding() { ) }); - // client request - let mut e = GzEncoder::new(Vec::new(), Compression::default()); - e.write_all(STR.as_ref()).unwrap(); - let enc = e.finish().unwrap(); - let request = srv .post("/") .insert_header((CONTENT_ENCODING, "gzip")) - .send_body(enc.clone()); - let mut response = request.await.unwrap(); - assert!(response.status().is_success()); + .send_body(gzip::encode(STR)); + let mut res = request.await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); + let bytes = res.body().await.unwrap(); assert_eq!(bytes, Bytes::from_static(STR.as_ref())); srv.stop().await; @@ -661,21 +509,15 @@ async fn test_gzip_encoding() { ) }); - // client request - let mut e = GzEncoder::new(Vec::new(), Compression::default()); - e.write_all(STR.as_ref()).unwrap(); - let enc = e.finish().unwrap(); - let request = srv .post("/") .append_header((CONTENT_ENCODING, "gzip")) - .send_body(enc.clone()); - let mut response = request.await.unwrap(); - assert!(response.status().is_success()); + .send_body(gzip::encode(STR)); + let mut res = request.await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); - assert_eq!(bytes, Bytes::from_static(STR.as_ref())); + let bytes = res.body().await.unwrap(); + assert_eq!(bytes, STR.as_bytes()); srv.stop().await; } @@ -689,21 +531,15 @@ async fn test_gzip_encoding_large() { ) }); - // client request - let mut e = GzEncoder::new(Vec::new(), Compression::default()); - e.write_all(data.as_ref()).unwrap(); - let enc = e.finish().unwrap(); - - let request = srv + let req = srv .post("/") .append_header((CONTENT_ENCODING, "gzip")) - .send_body(enc.clone()); - let mut response = request.await.unwrap(); - assert!(response.status().is_success()); + .send_body(gzip::encode(&data)); + let mut res = req.await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); - assert_eq!(bytes, Bytes::from(data)); + let bytes = res.body().await.unwrap(); + assert_eq!(bytes, data); srv.stop().await; } @@ -722,22 +558,15 @@ async fn test_reading_gzip_encoding_large_random() { ) }); - // client request - let mut e = GzEncoder::new(Vec::new(), Compression::default()); - e.write_all(data.as_ref()).unwrap(); - let enc = e.finish().unwrap(); - let request = srv .post("/") .append_header((CONTENT_ENCODING, "gzip")) - .send_body(enc.clone()); - let mut response = request.await.unwrap(); - assert!(response.status().is_success()); + .send_body(gzip::encode(&data)); + let mut res = request.await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); - assert_eq!(bytes.len(), data.len()); - assert_eq!(bytes, Bytes::from(data)); + let bytes = res.body().await.unwrap(); + assert_eq!(bytes, data.as_bytes()); srv.stop().await; } @@ -750,20 +579,14 @@ async fn test_reading_deflate_encoding() { ) }); - let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); - e.write_all(STR.as_ref()).unwrap(); - let enc = e.finish().unwrap(); - - // client request let request = srv .post("/") .append_header((CONTENT_ENCODING, "deflate")) - .send_body(enc.clone()); - let mut response = request.await.unwrap(); - assert!(response.status().is_success()); + .send_body(deflate::encode(STR)); + let mut res = request.await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); + let bytes = res.body().await.unwrap(); assert_eq!(bytes, Bytes::from_static(STR.as_ref())); srv.stop().await; @@ -778,20 +601,14 @@ async fn test_reading_deflate_encoding_large() { ) }); - let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); - e.write_all(data.as_ref()).unwrap(); - let enc = e.finish().unwrap(); - - // client request let request = srv .post("/") .append_header((CONTENT_ENCODING, "deflate")) - .send_body(enc.clone()); - let mut response = request.await.unwrap(); - assert!(response.status().is_success()); + .send_body(deflate::encode(&data)); + let mut res = request.await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); + let bytes = res.body().await.unwrap(); assert_eq!(bytes, Bytes::from(data)); srv.stop().await; @@ -811,20 +628,14 @@ async fn test_reading_deflate_encoding_large_random() { ) }); - let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); - e.write_all(data.as_ref()).unwrap(); - let enc = e.finish().unwrap(); - - // client request let request = srv .post("/") .append_header((CONTENT_ENCODING, "deflate")) - .send_body(enc.clone()); - let mut response = request.await.unwrap(); - assert!(response.status().is_success()); + .send_body(deflate::encode(&data)); + let mut res = request.await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); + let bytes = res.body().await.unwrap(); assert_eq!(bytes.len(), data.len()); assert_eq!(bytes, Bytes::from(data)); @@ -839,20 +650,14 @@ async fn test_brotli_encoding() { ) }); - let mut e = BrotliEncoder::new(Vec::new(), 5); - e.write_all(STR.as_ref()).unwrap(); - let enc = e.finish().unwrap(); - - // client request let request = srv .post("/") .append_header((CONTENT_ENCODING, "br")) - .send_body(enc.clone()); - let mut response = request.await.unwrap(); - assert!(response.status().is_success()); + .send_body(brotli::encode(STR)); + let mut res = request.await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); + let bytes = res.body().await.unwrap(); assert_eq!(bytes, Bytes::from_static(STR.as_ref())); srv.stop().await; @@ -876,20 +681,14 @@ async fn test_brotli_encoding_large() { ) }); - let mut e = BrotliEncoder::new(Vec::new(), 5); - e.write_all(data.as_ref()).unwrap(); - let enc = e.finish().unwrap(); - - // client request let request = srv .post("/") .append_header((CONTENT_ENCODING, "br")) - .send_body(enc.clone()); - let mut response = request.await.unwrap(); - assert!(response.status().is_success()); + .send_body(brotli::encode(&data)); + let mut res = request.await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().limit(320_000).await.unwrap(); + let bytes = res.body().limit(320_000).await.unwrap(); assert_eq!(bytes, Bytes::from(data)); srv.stop().await; @@ -898,6 +697,8 @@ async fn test_brotli_encoding_large() { #[cfg(feature = "openssl")] #[actix_rt::test] async fn test_brotli_encoding_large_openssl() { + use actix_web::http::header; + let data = STR.repeat(10); let srv = actix_test::start_with(actix_test::config().openssl(openssl_config()), move || { @@ -908,22 +709,15 @@ async fn test_brotli_encoding_large_openssl() { }))) }); - // body - let mut enc = BrotliEncoder::new(Vec::new(), 3); - enc.write_all(data.as_ref()).unwrap(); - let enc = enc.finish().unwrap(); - - // client request - let mut response = srv + let mut res = srv .post("/") - .append_header((actix_web::http::header::CONTENT_ENCODING, "br")) - .send_body(enc) + .append_header((header::CONTENT_ENCODING, "br")) + .send_body(brotli::encode(&data)) .await .unwrap(); - assert!(response.status().is_success()); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); + let bytes = res.body().await.unwrap(); assert_eq!(bytes, Bytes::from(data)); srv.stop().await; @@ -981,17 +775,15 @@ mod plus_rustls { e.write_all(data.as_ref()).unwrap(); let enc = e.finish().unwrap(); - // client request let req = srv .post("/") .insert_header((actix_web::http::header::CONTENT_ENCODING, "deflate")) .send_stream(TestBody::new(Bytes::from(enc), 1024)); - let mut response = req.await.unwrap(); - assert!(response.status().is_success()); + let mut res = req.await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); - // read response - let bytes = response.body().await.unwrap(); + let bytes = res.body().await.unwrap(); assert_eq!(bytes.len(), data.len()); assert_eq!(bytes, Bytes::from(data)); @@ -1084,8 +876,8 @@ async fn test_normalize() { .service(web::resource("/one").route(web::to(HttpResponse::Ok))) }); - let response = srv.get("/one/").send().await.unwrap(); - assert!(response.status().is_success()); + let res = srv.get("/one/").send().await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); srv.stop().await } @@ -1148,15 +940,20 @@ async fn test_accept_encoding_no_match() { .service(web::resource("/").route(web::to(move || HttpResponse::Ok().finish()))) }); - let response = srv + let mut res = srv .get("/") - .append_header((ACCEPT_ENCODING, "compress, identity;q=0")) + .insert_header((ACCEPT_ENCODING, "xz, identity;q=0")) .no_decompress() .send() .await .unwrap(); - assert_eq!(response.status().as_u16(), 406); + assert_eq!(res.status(), StatusCode::NOT_ACCEPTABLE); + assert_eq!(res.headers().get(CONTENT_ENCODING), None); + + let bytes = res.body().await.unwrap(); + // body should contain the supported encodings + assert!(!bytes.is_empty()); srv.stop().await; } diff --git a/tests/test_utils.rs b/tests/test_utils.rs new file mode 100644 index 000000000..d74143f57 --- /dev/null +++ b/tests/test_utils.rs @@ -0,0 +1,73 @@ +use std::io::{Read as _, Write as _}; + +pub mod gzip { + use super::*; + use flate2::{read::GzDecoder, write::GzEncoder, Compression}; + + pub fn encode(bytes: impl AsRef<[u8]>) -> Vec { + let mut encoder = GzEncoder::new(Vec::new(), Compression::fast()); + encoder.write_all(bytes.as_ref()).unwrap(); + encoder.finish().unwrap() + } + + pub fn decode(bytes: impl AsRef<[u8]>) -> Vec { + let mut decoder = GzDecoder::new(bytes.as_ref()); + let mut buf = Vec::new(); + decoder.read_to_end(&mut buf).unwrap(); + buf + } +} + +pub mod deflate { + use super::*; + use flate2::{read::ZlibDecoder, write::ZlibEncoder, Compression}; + + pub fn encode(bytes: impl AsRef<[u8]>) -> Vec { + let mut encoder = ZlibEncoder::new(Vec::new(), Compression::fast()); + encoder.write_all(bytes.as_ref()).unwrap(); + encoder.finish().unwrap() + } + + pub fn decode(bytes: impl AsRef<[u8]>) -> Vec { + let mut decoder = ZlibDecoder::new(bytes.as_ref()); + let mut buf = Vec::new(); + decoder.read_to_end(&mut buf).unwrap(); + buf + } +} + +pub mod brotli { + use super::*; + use ::brotli2::{read::BrotliDecoder, write::BrotliEncoder}; + + pub fn encode(bytes: impl AsRef<[u8]>) -> Vec { + let mut encoder = BrotliEncoder::new(Vec::new(), 3); + encoder.write_all(bytes.as_ref()).unwrap(); + encoder.finish().unwrap() + } + + pub fn decode(bytes: impl AsRef<[u8]>) -> Vec { + let mut decoder = BrotliDecoder::new(bytes.as_ref()); + let mut buf = Vec::new(); + decoder.read_to_end(&mut buf).unwrap(); + buf + } +} + +pub mod zstd { + use super::*; + use ::zstd::stream::{read::Decoder, write::Encoder}; + + pub fn encode(bytes: impl AsRef<[u8]>) -> Vec { + let mut encoder = Encoder::new(Vec::new(), 3).unwrap(); + encoder.write_all(bytes.as_ref()).unwrap(); + encoder.finish().unwrap() + } + + pub fn decode(bytes: impl AsRef<[u8]>) -> Vec { + let mut decoder = Decoder::new(bytes.as_ref()).unwrap(); + let mut buf = Vec::new(); + decoder.read_to_end(&mut buf).unwrap(); + buf + } +}