Skip to content

blackbull.server.permessage_deflate

blackbull.server.permessage_deflate

WebSocket compression negotiation and per-connection codec state.

Keep RSV1 framing in the WebSocket codec and recipient; negotiated context takeover governs reuse across messages.

DeflateParams dataclass

Per-connection permessage-deflate parameters as negotiated.

InboundDecompressor

Streaming decompressor for inbound permessage-deflate messages.

The peer (client) is doing the compression here, so the no_context_takeover flag we care about is client_no_context_takeover. When set, the inflater is recreated for every message; otherwise the same inflater is reused so the sliding-window context carries forward across messages.

decompress(payload, *, max_length=None)

Inflate one whole compressed message. Raises zlib.error on bad data.

With max_length set, the inflated output is bounded by zlib itself rather than measured after the fact: a bomb is refused without ever being built. Asking for max_length + 1 is what makes "exactly at the bound" and "one byte over" distinguishable in a single call — zlib stops at the byte it was given, so a return of exactly max_length bytes is ambiguous on its own.

Raises MessageTooLarge when the peer's message inflates past the bound. unconsumed_tail is the other half of that check: zlib stops early when it hits the limit, so leftover input means there was more to come even if the output landed on the boundary.

OutboundCompressor

Streaming compressor for outbound permessage-deflate messages.

Symmetric to InboundDecompressor: the no_context_takeover flag that matters here is server_no_context_takeover (we are the server), deciding whether to reset the deflater between messages.

compress(payload)

Compress one whole message; strip the trailing 0x00 0x00 0xff 0xff per RFC 7692 §7.2.1.

negotiate(offer_header)

Decide whether to accept permessage-deflate based on the client's offer.

Returns (params, response_value) where:

  • params is the DeflateParams to install on the connection (or None to decline).
  • response_value is the bytes to put after Sec-WebSocket-Extensions: in the 101 response (or None when declining).

Policy: accept context-takeover by default on both sides (better compression). Honour server_no_context_takeover and client_no_context_takeover when the client asks for them.

offer_header is the raw bytes of the client's Sec-WebSocket-Extensions header (or None when absent). The client may send multiple comma-separated offers; we pick the first one that names permessage-deflate and that we can satisfy.

negotiate_offer(headers)

Apply the settings gate and negotiate the RFC 7692 offer in headers.

The one way both handshakes (HTTP/1.1 and the RFC 8441 path) decide on permessage-deflate. Returns what negotiate returns: (params, response_value), both None when nothing was offered, the offer was declined, or ws_permessage_deflate is off.