Skip to main content

Crate churust_compression

Crate churust_compression 

Source
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 with compressible.
  • Responses that already carry a Content-Encoding.
  • 206 Partial Content and anything carrying Content-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§

Encoding
A supported content coding.
Level
How hard the encoder works.

Functions§

compressible_by_default
Whether a media type is worth compressing.