Streaming & SSE
Status: 🔴 DA REVISIONARE
What it does
Sends a response body incrementally instead of all at once. StreamingResponse
streams arbitrary chunks; SseStream streams Server-Sent Events with the correct
SSE framing and headers.
When to use it
When the body is large, generated lazily, or open-ended: a file too big to buffer,
a progress feed, live updates pushed to the browser. Use StreamingResponse for
raw chunks and SseStream for an event stream a browser’s EventSource can
consume.
Setup
Both types import from submodules — they are not re-exported from the package top level:
from genro_asgi.streaming import StreamingResponse
from genro_asgi.sse import SseStream
Chunked streaming
Return a StreamingResponse fed by an async generator that yields bytes:
from genro_asgi.streaming import StreamingResponse
async def chunks():
yield b"one"
yield b"two"
resp = StreamingResponse(chunks(), media_type="text/plain")
Each yielded chunk is sent as it is produced, so the client starts receiving before the generator finishes.
Server-Sent Events
Wrap an async source of events in an SseStream and turn it into a response:
from genro_asgi.sse import SseStream
async def source(*evts):
for e in evts:
yield e
stream = SseStream(source({"data": "a"}, {"data": "b"}), retry_ms=5000)
resp = stream.response() # a StreamingResponse with the SSE headers set
The source yields event dicts (
{"data": ...}).retry_mssets the client’s reconnection hint..response()returns aStreamingResponsealready carrying the SSE headers, so you return it like any other response.
How to verify it
For chunked output:
$ curl -N http://127.0.0.1:8000/<your-route>
onetwo
For SSE, curl -N shows the event frames as they arrive:
$ curl -N http://127.0.0.1:8000/<your-sse-route>
data: a
data: b
The -N flag disables curl’s buffering so you see chunks as they come.
Gotchas
Import from the submodules:
from genro_asgi.streaming import StreamingResponseandfrom genro_asgi.sse import SseStream. Neither is available asfrom genro_asgi import ....SseStreamproduces aStreamingResponsevia.response()— that is what you return; do not return theSseStreamitself.The MCP push stream (
GET /mcp) is built on this same SSE machinery; it depends on the task backbone being armed (see tasks and MCP).