From: Tom Christie Date: Tue, 14 Jan 2020 09:00:52 +0000 (+0000) Subject: Support both zlib and deflate encodings (#758) X-Git-Tag: 0.11.1~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=780d1843cac3487d545fd7b1ff44c1212702598a;p=thirdparty%2Fhttpx.git Support both zlib and deflate encodings (#758) * Support both zlib and deflate encodings * Helpful test docstrings --- diff --git a/httpx/decoders.py b/httpx/decoders.py index 75d980d3..454ec4a1 100644 --- a/httpx/decoders.py +++ b/httpx/decoders.py @@ -45,12 +45,18 @@ class DeflateDecoder(Decoder): """ def __init__(self) -> None: - self.decompressor = zlib.decompressobj(-zlib.MAX_WBITS) + self.first_attempt = True + self.decompressor = zlib.decompressobj() def decode(self, data: bytes) -> bytes: + was_first_attempt = self.first_attempt + self.first_attempt = False try: return self.decompressor.decompress(data) except zlib.error as exc: + if was_first_attempt: + self.decompressor = zlib.decompressobj(-zlib.MAX_WBITS) + return self.decode(data) raise DecodingError from exc def flush(self) -> bytes: diff --git a/tests/test_decoders.py b/tests/test_decoders.py index f320d941..d9e82f70 100644 --- a/tests/test_decoders.py +++ b/tests/test_decoders.py @@ -18,6 +18,11 @@ REQUEST = httpx.Request("GET", "https://example.org") def test_deflate(): + """ + Deflate encoding may use either 'zlib' or 'deflate' in the wild. + + https://stackoverflow.com/questions/1838699/how-can-i-decompress-a-gzip-stream-with-zlib#answer-22311297 + """ body = b"test 123" compressor = zlib.compressobj(9, zlib.DEFLATED, -zlib.MAX_WBITS) compressed_body = compressor.compress(body) + compressor.flush() @@ -29,6 +34,22 @@ def test_deflate(): assert response.content == body +def test_zlib(): + """ + Deflate encoding may use either 'zlib' or 'deflate' in the wild. + + https://stackoverflow.com/questions/1838699/how-can-i-decompress-a-gzip-stream-with-zlib#answer-22311297 + """ + body = b"test 123" + compressed_body = zlib.compress(body) + + headers = [(b"Content-Encoding", b"deflate")] + response = httpx.Response( + 200, headers=headers, content=compressed_body, request=REQUEST + ) + assert response.content == body + + def test_gzip(): body = b"test 123" compressor = zlib.compressobj(9, zlib.DEFLATED, zlib.MAX_WBITS | 16)