diff --git a/starlette/responses.py b/starlette/responses.py index 15292f0e7..047ff9561 100644 --- a/starlette/responses.py +++ b/starlette/responses.py @@ -207,7 +207,7 @@ def __init__( self.headers["location"] = quote(str(url), safe=":/%#?=@[]!$&'()*+,;") -Content = typing.Union[str, bytes] +Content = typing.Union[str, bytes, memoryview] SyncContentStream = typing.Iterable[Content] AsyncContentStream = typing.AsyncIterable[Content] ContentStream = typing.Union[AsyncContentStream, SyncContentStream] @@ -248,7 +248,7 @@ async def stream_response(self, send: Send) -> None: } ) async for chunk in self.body_iterator: - if not isinstance(chunk, bytes): + if not isinstance(chunk, (bytes, memoryview)): chunk = chunk.encode(self.charset) await send({"type": "http.response.body", "body": chunk, "more_body": True}) diff --git a/tests/test_responses.py b/tests/test_responses.py index a3cdcadcf..fa3c1009f 100644 --- a/tests/test_responses.py +++ b/tests/test_responses.py @@ -541,6 +541,13 @@ def test_streaming_response_known_size(test_client_factory: TestClientFactory) - assert response.headers["content-length"] == "10" +def test_streaming_response_memoryview(test_client_factory: TestClientFactory) -> None: + app = StreamingResponse(content=iter([memoryview(b"hello"), memoryview(b"world")])) + client: TestClient = test_client_factory(app) + response = client.get("/") + assert response.text == "helloworld" + + @pytest.mark.anyio async def test_streaming_response_stops_if_receiving_http_disconnect() -> None: streamed = 0