mirror of
https://github.com/fafhrd91/actix-web
synced 2024-12-04 20:31:55 +01:00
314 lines
9.3 KiB
Rust
314 lines
9.3 KiB
Rust
|
use actix_http::ContentEncoding;
|
||
|
use actix_web::{
|
||
|
dev::BodyEncoding as _,
|
||
|
http::{header, StatusCode},
|
||
|
middleware::Compress,
|
||
|
web, App, HttpResponse,
|
||
|
};
|
||
|
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");
|
||
|
static LOREM_ZSTD: &[u8] = include_bytes!("fixtures/lorem.txt.zst");
|
||
|
static LOREM_XZ: &[u8] = include_bytes!("fixtures/lorem.txt.xz");
|
||
|
|
||
|
macro_rules! test_server {
|
||
|
() => {
|
||
|
actix_test::start(|| {
|
||
|
App::new()
|
||
|
.wrap(Compress::default())
|
||
|
.route("/static", web::to(|| HttpResponse::Ok().body(LOREM)))
|
||
|
.route(
|
||
|
"/static-gzip",
|
||
|
web::to(|| {
|
||
|
HttpResponse::Ok()
|
||
|
// signal to compressor that content should not be altered
|
||
|
.encode_with(ContentEncoding::Identity)
|
||
|
// signal to client that content is encoded
|
||
|
.insert_header(ContentEncoding::Gzip)
|
||
|
.body(LOREM_GZIP)
|
||
|
}),
|
||
|
)
|
||
|
.route(
|
||
|
"/static-br",
|
||
|
web::to(|| {
|
||
|
HttpResponse::Ok()
|
||
|
// signal to compressor that content should not be altered
|
||
|
.encode_with(ContentEncoding::Identity)
|
||
|
// signal to client that content is encoded
|
||
|
.insert_header(ContentEncoding::Brotli)
|
||
|
.body(LOREM_BR)
|
||
|
}),
|
||
|
)
|
||
|
.route(
|
||
|
"/static-zstd",
|
||
|
web::to(|| {
|
||
|
HttpResponse::Ok()
|
||
|
// signal to compressor that content should not be altered
|
||
|
.encode_with(ContentEncoding::Identity)
|
||
|
// signal to client that content is encoded
|
||
|
.insert_header(ContentEncoding::Zstd)
|
||
|
.body(LOREM_ZSTD)
|
||
|
}),
|
||
|
)
|
||
|
.route(
|
||
|
"/static-xz",
|
||
|
web::to(|| {
|
||
|
HttpResponse::Ok()
|
||
|
// signal to compressor that content should not be altered
|
||
|
.encode_with(ContentEncoding::Identity)
|
||
|
// signal to client that content is encoded as 7zip
|
||
|
.insert_header((header::CONTENT_ENCODING, "xz"))
|
||
|
.body(LOREM_XZ)
|
||
|
}),
|
||
|
)
|
||
|
.route(
|
||
|
"/echo",
|
||
|
web::to(|body: Bytes| HttpResponse::Ok().body(body)),
|
||
|
)
|
||
|
})
|
||
|
};
|
||
|
}
|
||
|
|
||
|
#[actix_rt::test]
|
||
|
async fn negotiate_encoding_identity() {
|
||
|
let srv = test_server!();
|
||
|
|
||
|
let req = srv
|
||
|
.post("/static")
|
||
|
.insert_header((header::ACCEPT_ENCODING, "identity"))
|
||
|
.send();
|
||
|
|
||
|
let mut res = req.await.unwrap();
|
||
|
assert_eq!(res.status(), StatusCode::OK);
|
||
|
assert_eq!(res.headers().get(header::CONTENT_ENCODING), None);
|
||
|
|
||
|
let bytes = res.body().await.unwrap();
|
||
|
assert_eq!(bytes, Bytes::from_static(LOREM));
|
||
|
|
||
|
srv.stop().await;
|
||
|
}
|
||
|
|
||
|
#[actix_rt::test]
|
||
|
async fn negotiate_encoding_gzip() {
|
||
|
let srv = test_server!();
|
||
|
|
||
|
let req = srv
|
||
|
.post("/static")
|
||
|
.insert_header((header::ACCEPT_ENCODING, "gzip,br,zstd"))
|
||
|
.send();
|
||
|
|
||
|
let mut res = req.await.unwrap();
|
||
|
assert_eq!(res.status(), StatusCode::OK);
|
||
|
assert_eq!(res.headers().get(header::CONTENT_ENCODING).unwrap(), "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;
|
||
|
}
|
||
|
|
||
|
#[actix_rt::test]
|
||
|
async fn negotiate_encoding_br() {
|
||
|
let srv = test_server!();
|
||
|
|
||
|
let req = srv
|
||
|
.post("/static")
|
||
|
.insert_header((header::ACCEPT_ENCODING, "br,zstd,gzip"))
|
||
|
.send();
|
||
|
|
||
|
let mut res = req.await.unwrap();
|
||
|
assert_eq!(res.status(), StatusCode::OK);
|
||
|
assert_eq!(res.headers().get(header::CONTENT_ENCODING).unwrap(), "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;
|
||
|
}
|
||
|
|
||
|
#[actix_rt::test]
|
||
|
async fn negotiate_encoding_zstd() {
|
||
|
let srv = test_server!();
|
||
|
|
||
|
let req = srv
|
||
|
.post("/static")
|
||
|
.insert_header((header::ACCEPT_ENCODING, "zstd,gzip,br"))
|
||
|
.send();
|
||
|
|
||
|
let mut res = req.await.unwrap();
|
||
|
assert_eq!(res.status(), StatusCode::OK);
|
||
|
assert_eq!(res.headers().get(header::CONTENT_ENCODING).unwrap(), "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;
|
||
|
}
|
||
|
|
||
|
#[cfg(all(
|
||
|
feature = "compress-brotli",
|
||
|
feature = "compress-gzip",
|
||
|
feature = "compress-zstd",
|
||
|
))]
|
||
|
#[actix_rt::test]
|
||
|
async fn client_encoding_prefers_brotli() {
|
||
|
let srv = test_server!();
|
||
|
|
||
|
let req = srv.post("/static").send();
|
||
|
|
||
|
let mut res = req.await.unwrap();
|
||
|
assert_eq!(res.status(), StatusCode::OK);
|
||
|
assert_eq!(res.headers().get(header::CONTENT_ENCODING).unwrap(), "br");
|
||
|
|
||
|
let bytes = res.body().await.unwrap();
|
||
|
assert_eq!(bytes, Bytes::from_static(LOREM));
|
||
|
|
||
|
srv.stop().await;
|
||
|
}
|
||
|
|
||
|
#[actix_rt::test]
|
||
|
async fn gzip_no_decompress() {
|
||
|
let srv = test_server!();
|
||
|
|
||
|
let req = srv
|
||
|
.post("/static-gzip")
|
||
|
// don't decompress response body
|
||
|
.no_decompress()
|
||
|
// signal that we want a compressed body
|
||
|
.insert_header((header::ACCEPT_ENCODING, "gzip,br,zstd"))
|
||
|
.send();
|
||
|
|
||
|
let mut res = req.await.unwrap();
|
||
|
assert_eq!(res.status(), StatusCode::OK);
|
||
|
assert_eq!(res.headers().get(header::CONTENT_ENCODING).unwrap(), "gzip");
|
||
|
|
||
|
let bytes = res.body().await.unwrap();
|
||
|
assert_eq!(bytes, Bytes::from_static(LOREM_GZIP));
|
||
|
|
||
|
srv.stop().await;
|
||
|
}
|
||
|
|
||
|
#[actix_rt::test]
|
||
|
async fn manual_custom_coding() {
|
||
|
let srv = test_server!();
|
||
|
|
||
|
let req = srv
|
||
|
.post("/static-xz")
|
||
|
// don't decompress response body
|
||
|
.no_decompress()
|
||
|
// signal that we want a compressed body
|
||
|
.insert_header((header::ACCEPT_ENCODING, "xz"))
|
||
|
.send();
|
||
|
|
||
|
let mut res = req.await.unwrap();
|
||
|
assert_eq!(res.status(), StatusCode::OK);
|
||
|
assert_eq!(res.headers().get(header::CONTENT_ENCODING).unwrap(), "xz");
|
||
|
|
||
|
let bytes = res.body().await.unwrap();
|
||
|
assert_eq!(bytes, Bytes::from_static(LOREM_XZ));
|
||
|
|
||
|
srv.stop().await;
|
||
|
}
|
||
|
|
||
|
#[actix_rt::test]
|
||
|
async fn deny_identity_coding() {
|
||
|
let srv = test_server!();
|
||
|
|
||
|
let req = srv
|
||
|
.post("/static")
|
||
|
// signal that we want a compressed body
|
||
|
.insert_header((header::ACCEPT_ENCODING, "br, identity;q=0"))
|
||
|
.send();
|
||
|
|
||
|
let mut res = req.await.unwrap();
|
||
|
assert_eq!(res.status(), StatusCode::OK);
|
||
|
assert_eq!(res.headers().get(header::CONTENT_ENCODING).unwrap(), "br");
|
||
|
|
||
|
let bytes = res.body().await.unwrap();
|
||
|
assert_eq!(bytes, Bytes::from_static(LOREM));
|
||
|
|
||
|
srv.stop().await;
|
||
|
}
|
||
|
|
||
|
#[actix_rt::test]
|
||
|
async fn deny_identity_coding_no_decompress() {
|
||
|
let srv = test_server!();
|
||
|
|
||
|
let req = srv
|
||
|
.post("/static-br")
|
||
|
// don't decompress response body
|
||
|
.no_decompress()
|
||
|
// signal that we want a compressed body
|
||
|
.insert_header((header::ACCEPT_ENCODING, "br, identity;q=0"))
|
||
|
.send();
|
||
|
|
||
|
let mut res = req.await.unwrap();
|
||
|
assert_eq!(res.status(), StatusCode::OK);
|
||
|
assert_eq!(res.headers().get(header::CONTENT_ENCODING).unwrap(), "br");
|
||
|
|
||
|
let bytes = res.body().await.unwrap();
|
||
|
assert_eq!(bytes, Bytes::from_static(LOREM_BR));
|
||
|
|
||
|
srv.stop().await;
|
||
|
}
|
||
|
|
||
|
// TODO: fix test
|
||
|
// currently fails because negotiation doesn't consider unknown encoding types
|
||
|
#[ignore]
|
||
|
#[actix_rt::test]
|
||
|
async fn deny_identity_for_manual_coding() {
|
||
|
let srv = test_server!();
|
||
|
|
||
|
let req = srv
|
||
|
.post("/static-xz")
|
||
|
// don't decompress response body
|
||
|
.no_decompress()
|
||
|
// signal that we want a compressed body
|
||
|
.insert_header((header::ACCEPT_ENCODING, "xz, identity;q=0"))
|
||
|
.send();
|
||
|
|
||
|
let mut res = req.await.unwrap();
|
||
|
assert_eq!(res.status(), StatusCode::OK);
|
||
|
assert_eq!(res.headers().get(header::CONTENT_ENCODING).unwrap(), "xz");
|
||
|
|
||
|
let bytes = res.body().await.unwrap();
|
||
|
assert_eq!(bytes, Bytes::from_static(LOREM_XZ));
|
||
|
|
||
|
srv.stop().await;
|
||
|
}
|