From 4d20d8ddfc74c33e93d3eef4cbf9168d8772a196 Mon Sep 17 00:00:00 2001 From: anthroposcene Date: Wed, 29 Apr 2026 02:55:29 -0700 Subject: [PATCH] add src/codec.py --- src/codec.py | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/codec.py diff --git a/src/codec.py b/src/codec.py new file mode 100644 index 0000000..34692da --- /dev/null +++ b/src/codec.py @@ -0,0 +1,92 @@ +""" +Content-Encoding decoders: gzip (stdlib), brotli (optional), zstd (optional). + +`decode(body, encoding)` returns the decoded bytes, or the original bytes +on any error. Use `supported_encodings()` to build an Accept-Encoding value. +""" + +from __future__ import annotations + +import gzip +import logging +import zlib + +log = logging.getLogger("Codec") + +try: + import brotli # type: ignore + _HAS_BR = True +except ImportError: # pragma: no cover + brotli = None # type: ignore + _HAS_BR = False + +try: + import zstandard as _zstd # type: ignore + _HAS_ZSTD = True + _ZSTD_DCTX = _zstd.ZstdDecompressor() +except ImportError: # pragma: no cover + _zstd = None # type: ignore + _HAS_ZSTD = False + _ZSTD_DCTX = None + + +def supported_encodings() -> str: + """Value for Accept-Encoding that this relay can actually decode.""" + codecs = ["gzip", "deflate"] + if _HAS_BR: + codecs.append("br") + if _HAS_ZSTD: + codecs.append("zstd") + return ", ".join(codecs) + + +def has_brotli() -> bool: + return _HAS_BR + + +def has_zstd() -> bool: + return _HAS_ZSTD + + +def decode(body: bytes, encoding: str) -> bytes: + """Decode *body* according to Content-Encoding. + + Returns the original bytes if the encoding is empty, unknown, or + decompression fails (so the caller can safely pass through). + """ + if not body: + return body + enc = (encoding or "").strip().lower() + if not enc or enc == "identity": + return body + + # Multi-coding (rare): "gzip, br" means brotli(gzip(data)) + if "," in enc: + for layer in reversed([s.strip() for s in enc.split(",") if s.strip()]): + body = decode(body, layer) + return body + + try: + if enc == "gzip": + return gzip.decompress(body) + if enc == "deflate": + try: + return zlib.decompress(body) + except zlib.error: + # Some servers send raw deflate without zlib wrapper. + return zlib.decompress(body, -zlib.MAX_WBITS) + if enc == "br": + if not _HAS_BR: + log.debug("brotli not installed — body passed through") + return body + return brotli.decompress(body) + if enc == "zstd": + if not _HAS_ZSTD: + log.debug("zstandard not installed — body passed through") + return body + return _ZSTD_DCTX.decompress(body) + except Exception as exc: + log.debug("decompress (%s) failed: %s — returning raw", enc, exc) + return body + + return body \ No newline at end of file