]> git.ipfire.org Git - thirdparty/httpx.git/commitdiff
Wrap decoding errors with custom exceptions
authorYeray Diaz Diaz <yeraydiazdiaz@gmail.com>
Fri, 26 Apr 2019 19:09:57 +0000 (20:09 +0100)
committerYeray Diaz Diaz <yeraydiazdiaz@gmail.com>
Sat, 27 Apr 2019 15:39:53 +0000 (16:39 +0100)
httpcore/__init__.py
httpcore/decoders.py
httpcore/exceptions.py
tests/test_decoding.py

index 9824e854e54223571979e8ac7ffcbf3606be02e4..7786c2595951b591e0c293abf2e1a33fd141de13 100644 (file)
@@ -9,6 +9,9 @@ from .exceptions import (
     ResponseClosed,
     StreamConsumed,
     Timeout,
+    DeflateDecodingError,
+    GzipDecodingError,
+    BrotliDecodingError,
 )
 from .http11 import HTTP11Connection
 from .sync import SyncClient, SyncConnectionPool
index b56745c49a5ca64c9c852f2eeae1d20f18c3dc32..dc56e1315803f93261ca633f6d5384fef39127a4 100644 (file)
@@ -12,6 +12,9 @@ except ImportError:  # pragma: nocover
     brotli = None
 
 
+import httpcore.exceptions
+
+
 class Decoder:
     def decode(self, data: bytes) -> bytes:
         raise NotImplementedError()  # pragma: nocover
@@ -39,10 +42,16 @@ class DeflateDecoder(Decoder):
         self.decompressor = zlib.decompressobj(-zlib.MAX_WBITS)
 
     def decode(self, data: bytes) -> bytes:
-        return self.decompressor.decompress(data)
+        try:
+            return self.decompressor.decompress(data)
+        except zlib.error as exc:
+            raise httpcore.exceptions.DeflateDecodingError from exc
 
     def flush(self) -> bytes:
-        return self.decompressor.flush()
+        try:
+            return self.decompressor.flush()
+        except zlib.error as exc:
+            raise httpcore.exceptions.DeflateDecodingError from exc
 
 
 class GZipDecoder(Decoder):
@@ -56,10 +65,16 @@ class GZipDecoder(Decoder):
         self.decompressor = zlib.decompressobj(zlib.MAX_WBITS | 16)
 
     def decode(self, data: bytes) -> bytes:
-        return self.decompressor.decompress(data)
+        try:
+            return self.decompressor.decompress(data)
+        except zlib.error as exc:
+            raise httpcore.exceptions.GzipDecodingError from exc
 
     def flush(self) -> bytes:
-        return self.decompressor.flush()
+        try:
+            return self.decompressor.flush()
+        except zlib.error as exc:
+            raise httpcore.exceptions.GzipDecodingError from exc
 
 
 class BrotliDecoder(Decoder):
@@ -77,16 +92,22 @@ class BrotliDecoder(Decoder):
         self.decompressor = brotli.Decompressor()
 
     def decode(self, data: bytes) -> bytes:
-        return self.decompressor.decompress(data)
+        try:
+            return self.decompressor.decompress(data)
+        except brotli.Error as exc:
+            raise httpcore.exceptions.BrotliDecodingError from exc
 
     def flush(self) -> bytes:
-        self.decompressor.finish()
-        return b""
+        try:
+            self.decompressor.finish()
+            return b""
+        except brotli.Error as exc:
+            raise httpcore.exceptions.BrotliDecodingError from exc
 
 
 class MultiDecoder(Decoder):
     """
-    Handle the case where mutliple encodings have been applied.
+    Handle the case where mutiple encodings have been applied.
     """
 
     def __init__(self, children: typing.Sequence[Decoder]) -> None:
index 30814332c3732b6e2bddd55aaf25f28f71b5501d..a85f128fa9a5541cab8fb8a5ab3302f83b68c9c5 100644 (file)
@@ -40,3 +40,27 @@ class ResponseClosed(Exception):
     Attempted to read or stream response content, but the request has been
     closed without loading the body.
     """
+
+
+class DecodingError(Exception):
+    """
+    Decoding of the response failed.
+    """
+
+
+class DeflateDecodingError(DecodingError):
+    """
+    Decoding of the response using deflate failed.
+    """
+
+
+class GzipDecodingError(DecodingError):
+    """
+    Decoding of the response using gzip failed.
+    """
+
+
+class BrotliDecodingError(DecodingError):
+    """
+    Decoding of the response using brotli failed.
+    """
index f08c0abfc1b647361747f58d621d50de29791814..c4a174667c03b05c8db36b8579f34f96e7f334e1 100644 (file)
@@ -77,3 +77,18 @@ async def test_streaming():
     response = httpcore.Response(200, headers=headers, body=compress(body))
     assert not hasattr(response, "body")
     assert await response.read() == body
+
+
+@pytest.mark.parametrize(
+    'header_value, expected_exception',
+    [
+        (b"deflate", httpcore.DeflateDecodingError),
+        (b"gzip", httpcore.GzipDecodingError),
+        (b"br", httpcore.BrotliDecodingError),
+    ])
+def test_decoding_errors(header_value, expected_exception):
+    headers = [(b"Content-Encoding", header_value)]
+    body = b"test 123"
+    compressed_body = brotli.compress(body)[3:]
+    with pytest.raises(expected_exception):
+        response = httpcore.Response(200, headers=headers, body=compressed_body)