Skip to main content

codings/
codings.rs

1//! Negotiate a coding from a response's headers, decode a body under it, and compress one on the
2//! way out.
3//!
4//! Run with `cargo run -p web-faith-encoding --example codings`.
5
6use bytes::Bytes;
7use futures::StreamExt as _;
8use http::{HeaderMap, HeaderValue};
9use web_faith_encoding::{
10	AcceptEncoding, Coding, DEFAULT_ACCEPT_ENCODING, compress_buffer, decision, decode_stream,
11	layer_content_encoding, strip_decoded_headers,
12};
13
14#[tokio::main]
15async fn main() {
16	let accept = AcceptEncoding::parse(DEFAULT_ACCEPT_ENCODING);
17
18	// What a response's headers negotiate against what the request asked for.
19	let mut headers = HeaderMap::new();
20	headers.insert("content-encoding", HeaderValue::from_static("gzip"));
21	headers.insert("content-length", HeaderValue::from_static("42"));
22	let coding = decision(&headers, &accept).expect("gzip is in the default Accept-Encoding");
23	println!("negotiated: {coding:?}");
24
25	// A decoded body's length and coding no longer describe what the caller receives.
26	strip_decoded_headers(&mut headers);
27	println!("headers after decoding: {:?}", headers.keys().count());
28
29	// Round-trip a body through the coding that was negotiated.
30	let original = b"the quick brown fox jumps over the lazy dog".repeat(8);
31	let compressed = compress_buffer(&original, coding)
32		.await
33		.expect("gzip compresses");
34	println!(
35		"{} bytes in, {} bytes out",
36		original.len(),
37		compressed.len()
38	);
39
40	let stream = futures::stream::once(async move { Ok(Bytes::from(compressed)) });
41	let mut decoded = decode_stream(Box::pin(stream), coding);
42	let mut round_tripped = Vec::new();
43	while let Some(chunk) = decoded.next().await {
44		round_tripped.extend_from_slice(&chunk.expect("the body decodes"));
45	}
46	println!("round-tripped intact: {}", round_tripped == original);
47
48	// A request that compresses on top of a coding the caller already applied names both, in order.
49	println!(
50		"Content-Encoding: {}",
51		layer_content_encoding(Some("br"), Coding::Gzip)
52	);
53}