Forward gzip Bytes with the Headers That Describe Them
Choose encoded or decoded payloads in a Requests-based proxy, then give the downstream response matching content headers and its own framing.
If Requests has already decompressed a body, forwarding it with Content-Encoding: gzip asks the next client to decompress it again. Decide which payload representation the proxy sends before copying its headers.
| Payload sent | Content headers |
|---|---|
| Original encoded bytes | Keep the applicable coding and exact payload length |
| Decoded bytes | Remove the decoded coding; remove or recompute the corresponding length |
For encoded payload bytes, this fragment reads urllib3's raw stream without content decoding:
with requests.get(url, stream=True, timeout=(5, 30)) as upstream:
upstream.raise_for_status()
for block in upstream.raw.stream(65536, decode_content=False):
downstream.write(block)downstream is the existing response output. Its status and headers must already follow the chosen policy; this fragment does not implement a complete proxy server.
Transfer framing is separate from gzip content coding. The upstream HTTP library has already handled framing, including chunk removal, so do not blindly copy Transfer-Encoding. The downstream server frames its own response even when the payload remains gzip-encoded.
response.text followed by UTF-8 encoding also changes representation and cannot preserve arbitrary binary data. Close or consume the upstream response on every path, and handle HTTP errors according to the proxy contract: this example raises them instead of forwarding them.