Expand description
Response compression for the Churust web framework.
Compression negotiates a content coding from the request’s
Accept-Encoding, compresses the response body, and sets
Content-Encoding. Brotli, gzip and deflate are supported. A streamed body
stays streamed: it is compressed chunk by chunk rather than collected first.
use churust_core::{Call, Churust, TestClient};
use churust_compression::Compression;
let app = Churust::server()
.install(Compression::new())
.routing(|r| {
r.get("/", |_c: Call| async { "hello ".repeat(500) });
})
.build();
let res = TestClient::new(app)
.get("/")
.header("accept-encoding", "gzip")
.send()
.await;
assert_eq!(res.header("content-encoding"), Some("gzip"));
assert_eq!(res.header("vary"), Some("accept-encoding"));§What is deliberately not compressed
Compression that saves nothing still costs CPU on both ends, and in a few cases it is wrong rather than merely wasteful. The plugin skips:
- Bodies below
min_size(1 KiB by default). Below roughly that size a gzip member’s own header eats the saving. - Content types that are already compressed (images, video, audio, archives)
or that are not known to be text, per
compressible_by_default. Override withcompressible. - Responses that already carry a
Content-Encoding. 206 Partial Contentand anything carryingContent-Range. The range was computed against the identity representation, so compressing the selected span would make the offsets describe bytes that are not there.- Statuses that carry no body at all (
1xx,204,304).
Vary: Accept-Encoding is added to every response the plugin sees, not
only compressed ones. A cache that stored one variant without it would serve
a brotli body to a client that never asked for one.
A HEAD reply is a case of its own. Its body is already gone by the time the
plugin runs, so there is nothing to encode, but the headers are still
rewritten exactly as they would be for the matching GET:
Content-Encoding set, the identity Content-Length and any
Accept-Ranges removed, a strong ETag weakened. RFC 9110 §9.3.2 asks a
HEAD to answer with the fields its GET would send, and a client or cache
that sizes a resource with HEAD before fetching it must not be told about
a representation the server will not deliver.
§Should this live in the application at all
Often it should not. A reverse proxy in front of the service can compress once for every backend behind it, and it is usually already terminating TLS and doing the buffering. Reach for this plugin when there is no such proxy, when the proxy is not under your control, or when a handler produces a stream long enough that you want it compressed before it crosses the network hop the proxy sits on.
Structs§
- Compression
- The response compression plugin.
Enums§
Functions§
- compressible_
by_ default - Whether a media type is worth compressing.