Skip to content

Commit

Permalink
Add basic streaming support
Browse files Browse the repository at this point in the history
Buffer and parse streamed requests.
  • Loading branch information
bennettgoble committed Mar 12, 2024
1 parent 19ab827 commit 1b90db3
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 7 deletions.
2 changes: 2 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[flake8]
extend-ignore = E203
9 changes: 2 additions & 7 deletions llsd_asgi/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,9 @@ async def receive_with_llsd(self) -> Message:
assert message["type"] == "http.request"

body = message["body"]
more_body = message.get("more_body", False)
if more_body:
# Some implementations (e.g. HTTPX) may send one more empty-body message.
# Make sure they don't send one that contains a body, or it means
# that clients attempt to stream the request body.
while message.get("more_body", False):
message = await self.receive()
if message["body"] != b"": # pragma: no cover
raise NotImplementedError("Streaming the request body isn't supported yet")
body += message["body"]

message["body"] = json.dumps(self.parse(body), cls=JSONEncoder).encode()

Expand Down
27 changes: 27 additions & 0 deletions tests/test_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,33 @@ async def app(scope: Scope, receive: Receive, send: Send) -> None:
)


@pytest.mark.asyncio
async def test_streaming_request() -> None:
async def app(scope: Scope, receive: Receive, send: Send) -> None:
request = Request(scope, receive=receive)
body = await request.json()
text = f"message={body['message']!r}"

response = PlainTextResponse(text)
await response(scope, receive, send)

app = LLSDMiddleware(app)

async def stream_bytes(content):
b = llsd.format_xml(content)
for chunk in range(0, len(b), 2):
yield b[chunk : chunk + 2]

async with httpx.AsyncClient(app=app, base_url="http://testserver") as client:
r = await client.post(
"/",
content=stream_bytes({"message": "Hello, world!"}),
headers={"content-type": "application/llsd+xml"},
)
assert r.status_code == 200
assert r.text == "message='Hello, world!'"


@pytest.mark.asyncio
async def test_non_llsd_request() -> None:
async def app(scope: Scope, receive: Receive, send: Send) -> None:
Expand Down

0 comments on commit 1b90db3

Please sign in to comment.