Skip to content

Commit fc2d503

Browse files
committed
IteratorByteStream: split large iterator chunks into 64KB pieces
1 parent a48f2ab commit fc2d503

2 files changed

Lines changed: 26 additions & 0 deletions

File tree

httpx/_content.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ def __iter__(self) -> Iterator[bytes]:
6868
yield part[offset : offset + chunk_size]
6969
offset += chunk_size
7070

71+
7172
class AsyncIteratorByteStream(AsyncByteStream):
7273
CHUNK_SIZE = 65_536
7374

tests/test_content.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,3 +516,28 @@ def test_allow_nan_false():
516516
ValueError, match="Out of range float values are not JSON compliant"
517517
):
518518
httpx.Response(200, json=data_with_inf)
519+
520+
521+
@pytest.mark.anyio
522+
async def test_iterator_content_splits_large_chunks():
523+
# Generator yielding a single large chunk (100 KB)
524+
large_chunk = b"a" * 102_400 # 100 KB
525+
526+
def gen() -> typing.Iterator[bytes]:
527+
yield large_chunk
528+
529+
# Pass generator to Request (internally uses IteratorByteStream)
530+
request = httpx.Request(method, url, content=gen())
531+
532+
# Cast to Iterable[bytes] to make mypy happy
533+
sync_stream: typing.Iterable[bytes] = request.stream # type: ignore
534+
535+
# Collect chunks
536+
chunks = list(sync_stream)
537+
538+
# Each chunk must be <= 64 KB
539+
for chunk in chunks:
540+
assert len(chunk) <= 64 * 1024
541+
542+
# Total content matches original
543+
assert b"".join(chunks) == large_chunk

0 commit comments

Comments
 (0)