use trillium::{Conn as ServerConn, KnownHeaderName::ContentType};
use trillium_client::{Client, KnownHeaderName::ContentEncoding, Status};
use trillium_compression::{CompressionAlgorithm, client::Compression};
use trillium_testing::{ServerConnector, TestResult, harness, test};
fn payload() -> String {
"the quick brown fox jumps over the lazy dog. ".repeat(200)
}
fn app() -> impl trillium::Handler {
(
trillium_compression::Compression::new(),
|conn: ServerConn| async move {
conn.with_response_header(ContentType, "text/plain")
.ok(payload())
},
)
}
fn echo_app() -> impl trillium::Handler {
|mut conn: ServerConn| async move {
let request_encoding = conn
.request_headers()
.get_str(ContentEncoding)
.map(String::from);
let body = conn.request_body().read_bytes().await.unwrap();
if let Some(encoding) = request_encoding {
conn.response_headers_mut()
.insert("x-request-content-encoding", encoding.clone())
.insert(ContentEncoding, encoding);
}
conn.ok(body)
}
}
#[test(harness)]
async fn decodes_compressed_response() -> TestResult {
let client = Client::new(ServerConnector::new(app())).with_handler(Compression::new());
let mut conn = client.get("http://example.com/").await?;
assert_eq!(conn.status(), Some(Status::Ok));
assert_eq!(conn.response_headers().get_str(ContentEncoding), None);
assert_eq!(conn.response_body().read_string().await?, payload());
Ok(())
}
#[test(harness)]
async fn server_actually_compresses_the_wire() -> TestResult {
let client = Client::new(ServerConnector::new(app()));
let mut conn = client
.get("http://example.com/")
.with_request_header("accept-encoding", "zstd")
.await?;
assert_eq!(
conn.response_headers().get_str(ContentEncoding),
Some("zstd")
);
let wire = conn.response_body().read_bytes().await?;
assert!(
wire.len() < payload().len(),
"expected compressed wire body ({} bytes) to be smaller than plaintext ({} bytes)",
wire.len(),
payload().len(),
);
Ok(())
}
#[test(harness)]
async fn compresses_request_with_default_encoding() -> TestResult {
let client = Client::new(ServerConnector::new(echo_app()))
.with_handler(Compression::new().with_default_encoding(CompressionAlgorithm::Zstd));
let mut conn = client
.post("http://example.com/")
.with_body(payload())
.await?;
assert_eq!(
conn.response_headers()
.get_str("x-request-content-encoding"),
Some("zstd")
);
assert_eq!(conn.response_body().read_string().await?, payload());
Ok(())
}
#[test(harness)]
async fn per_request_state_selects_encoding() -> TestResult {
let client = Client::new(ServerConnector::new(echo_app())).with_handler(Compression::new());
let mut conn = client
.post("http://example.com/")
.with_body(payload())
.with_state(CompressionAlgorithm::Gzip)
.await?;
assert_eq!(
conn.response_headers()
.get_str("x-request-content-encoding"),
Some("gzip")
);
assert_eq!(conn.response_body().read_string().await?, payload());
Ok(())
}
#[test(harness)]
async fn identity_state_opts_out_of_default() -> TestResult {
let client = Client::new(ServerConnector::new(echo_app()))
.with_handler(Compression::new().with_default_encoding(CompressionAlgorithm::Zstd));
let mut conn = client
.post("http://example.com/")
.with_body(payload())
.with_state(CompressionAlgorithm::Identity)
.await?;
assert_eq!(
conn.response_headers()
.get_str("x-request-content-encoding"),
None
);
assert_eq!(conn.response_body().read_string().await?, payload());
Ok(())
}