diff --git a/docs/api.md b/docs/api.md index f1bd50c993..5b189eb06e 100644 --- a/docs/api.md +++ b/docs/api.md @@ -100,7 +100,7 @@ what gets sent over the wire.* * `def __init__(method, url, [params], [headers], [cookies], [content], [data], [files], [json], [stream])` * `.method` - **str** * `.url` - **URL** -* `.content` - **byte**, **byte iterator**, or **byte async iterator** +* `.content` - **byte**, **bytearray**, **byte iterator**, or **byte async iterator** * `.headers` - **Headers** * `.cookies` - **Cookies** diff --git a/httpx/_content.py b/httpx/_content.py index 6f479a0885..2d2421577b 100644 --- a/httpx/_content.py +++ b/httpx/_content.py @@ -105,9 +105,9 @@ async def __aiter__(self) -> AsyncIterator[bytes]: def encode_content( - content: str | bytes | Iterable[bytes] | AsyncIterable[bytes], + content: str | bytes | bytearray | Iterable[bytes] | AsyncIterable[bytes], ) -> tuple[dict[str, str], SyncByteStream | AsyncByteStream]: - if isinstance(content, (bytes, str)): + if isinstance(content, (bytes, bytearray, str)): body = content.encode("utf-8") if isinstance(content, str) else content content_length = len(body) headers = {"Content-Length": str(content_length)} if body else {} diff --git a/httpx/_types.py b/httpx/_types.py index 704dfdffc8..76fa3057ce 100644 --- a/httpx/_types.py +++ b/httpx/_types.py @@ -65,7 +65,7 @@ "Auth", ] -RequestContent = Union[str, bytes, Iterable[bytes], AsyncIterable[bytes]] +RequestContent = Union[str, bytes, bytearray, Iterable[bytes], AsyncIterable[bytes]] ResponseContent = Union[str, bytes, Iterable[bytes], AsyncIterable[bytes]] ResponseExtensions = Mapping[str, Any] diff --git a/test b/test new file mode 100644 index 0000000000..a7c01bc6a4 --- /dev/null +++ b/test @@ -0,0 +1 @@ +# TLS secrets log file, generated by OpenSSL / Python diff --git a/tests/test_content.py b/tests/test_content.py index f63ec18a6b..e987104a9a 100644 --- a/tests/test_content.py +++ b/tests/test_content.py @@ -50,6 +50,30 @@ async def test_bytes_content(): assert async_content == b"Hello, world!" +@pytest.mark.anyio +async def test_bytearray_content(): + request = httpx.Request(method, url, content=b"Hello, world!") + assert isinstance(request.stream, typing.Iterable) + assert isinstance(request.stream, typing.AsyncIterable) + + sync_content = b"".join(list(request.stream)) + async_content = b"".join([part async for part in request.stream]) + + assert request.headers == {"Host": "www.example.com", "Content-Length": "13"} + assert sync_content == b"Hello, world!" + assert async_content == b"Hello, world!" + + assert isinstance(request.stream, typing.Iterable) + assert isinstance(request.stream, typing.AsyncIterable) + + sync_content = b"".join(list(request.stream)) + async_content = b"".join([part async for part in request.stream]) + + assert request.headers == {"Host": "www.example.com", "Content-Length": "13"} + assert sync_content == b"Hello, world!" + assert async_content == b"Hello, world!" + + @pytest.mark.anyio async def test_bytesio_content(): request = httpx.Request(method, url, content=io.BytesIO(b"Hello, world!"))