]> git.ipfire.org Git - thirdparty/httpx.git/commitdiff
Handle empty zstd responses (#3412)
authorTom Christie <tom@tomchristie.com>
Fri, 22 Nov 2024 11:42:51 +0000 (11:42 +0000)
committerGitHub <noreply@github.com>
Fri, 22 Nov 2024 11:42:51 +0000 (11:42 +0000)
CHANGELOG.md
README.md
httpx/__version__.py
httpx/_decoders.py
tests/test_decoders.py

index 3c16d6671f7a3478a0dd88f04f89ab862f131e78..4e2afe2e621af9e0e82b8263af68bf6c681f4486 100644 (file)
@@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file.
 
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 
-## [Unreleased]
+## 0.28.0 (...)
 
 The 0.28 release includes a limited set of backwards incompatible changes.
 
index d5d21487133816b7c4bdf45b2ee8b98b96895690..23992d9c24c07f7e835d39f65e28f9055aa0926c 100644 (file)
--- a/README.md
+++ b/README.md
@@ -13,9 +13,7 @@
 </a>
 </p>
 
-HTTPX is a fully featured HTTP client library for Python 3. It includes **an integrated
-command line client**, has support for both **HTTP/1.1 and HTTP/2**, and provides both **sync
-and async APIs**.
+HTTPX is a fully featured HTTP client library for Python 3. It includes **an integrated command line client**, has support for both **HTTP/1.1 and HTTP/2**, and provides both **sync and async APIs**.
 
 ---
 
index 5eaaddbac9900b22dc569acbc3845c9c2d92ba59..0a684ac3a94b07906f2dc76f4c85136297a9bfd8 100644 (file)
@@ -1,3 +1,3 @@
 __title__ = "httpx"
 __description__ = "A next generation HTTP client, for Python 3."
-__version__ = "0.27.2"
+__version__ = "0.28.0"
index 180898c53f7c15c42b7cbe2a7a45290bc2af4b7f..899dfada878e1181fca6d3c75a79526a076abb9e 100644 (file)
@@ -175,9 +175,11 @@ class ZStandardDecoder(ContentDecoder):
             ) from None
 
         self.decompressor = zstandard.ZstdDecompressor().decompressobj()
+        self.seen_data = False
 
     def decode(self, data: bytes) -> bytes:
         assert zstandard is not None
+        self.seen_data = True
         output = io.BytesIO()
         try:
             output.write(self.decompressor.decompress(data))
@@ -190,6 +192,8 @@ class ZStandardDecoder(ContentDecoder):
         return output.getvalue()
 
     def flush(self) -> bytes:
+        if not self.seen_data:
+            return b""
         ret = self.decompressor.flush()  # note: this is a no-op
         if not self.decompressor.eof:
             raise DecodingError("Zstandard data is incomplete")  # pragma: no cover
index bcbb18bb0ebc74dba17cde25058268ec5419769e..9ffaba189d03052e88a77403bc5b1ebb07f32d3e 100644 (file)
@@ -100,6 +100,25 @@ def test_zstd_decoding_error():
         )
 
 
+def test_zstd_empty():
+    headers = [(b"Content-Encoding", b"zstd")]
+    response = httpx.Response(200, headers=headers, content=b"")
+    assert response.content == b""
+
+
+def test_zstd_truncated():
+    body = b"test 123"
+    compressed_body = zstd.compress(body)
+
+    headers = [(b"Content-Encoding", b"zstd")]
+    with pytest.raises(httpx.DecodingError):
+        httpx.Response(
+            200,
+            headers=headers,
+            content=compressed_body[1:3],
+        )
+
+
 def test_zstd_multiframe():
     # test inspired by urllib3 test suite
     data = (