Flask Stream Helpers Api
## Flask Stream Helpers API
In Flask, streaming responses allow you to send data back to the client in chunks rather than waiting for the entire response to be generated. However, because Flask tears down the request context as soon as the view function returns, a standard generator running inside a streaming response cannot access request-bound globals like `request`, `session`, or `g`.
To solve this, Flask provides the `stream_with_context` helper. It keeps the request context alive during the entire lifetime of the generator, ensuring you can safely access request data while streaming.
---
## stream_with_context
The `stream_with_context` utility is used to wrap or decorate a generator function so that the Flask request context remains active while the generator is being executed.
### API Parameter
| Parameter | Type | Description |
| :--- | :--- | :--- |
| `generator_or_function` | iterator / callable | The generator function or callable object. It can be used either as a decorator or as a wrapper function. |
---
## Two Ways to Use stream_with_context
You can apply `stream_with_context` in two different patterns depending on your coding style:
| Usage Pattern | Description |
| :--- | :--- |
| **Decorator Pattern** | Use `@stream_with_context` directly above the inner generator function definition. |
| **Wrapper Pattern** | Pass the instantiated generator object into `stream_with_context(generator())` when returning the response. |
---
## Code Examples
Here is a complete Flask application demonstrating both patterns.
```python
from flask import Flask, stream_with_context, request, Response
import time
app = Flask(__name__)
@app.get("/stream")
def streamed_response():
"""
Streaming response example using the Decorator Pattern.
This streams Server-Sent Events (SSE) line by line.
"""
@stream_with_context
def generate():
# Even though the response has started sending, we can still safely access `request`
visitor_name = request.args.get('name', 'YouTip User')
yield f"data: Hello {visitor_name}\n\n"
for i in range(5):
time.sleep(0.5) # Simulate a time-consuming task
yield f"data: Line {i}\n\n"
yield "data: \n\n"
return Response(generate(), mimetype="text/event-stream")
@app.get("/stream-wrap")
def stream_wrap():
"""
Streaming response example using the Wrapper Pattern.
"""
def generate():
yield "Hello "
# Accessing request context inside the generator
yield request.args.get("name", "World")
yield "!"
# Wrap the instantiated generator with stream_with_context
return Response(stream_with_context(generate()))
if __name__ == "__main__":
app.run(debug=True)
```
---
## Important Considerations
When working with streaming responses and `stream_with_context`, keep the following best practices in mind:
1. **HTTP Headers are Immutable Once Streaming Starts**:
HTTP headers are sent to the client at the very beginning of the response. Once your generator yields its first chunk of data, the headers are locked and sent. You cannot modify headers, set cookies, or change the status code from inside the generator after streaming has begun.
2. **Session Access and Cookie Headers**:
If your generator needs to access or modify the `session`, you must access the session in the main view function *before* returning the `Response` object. This triggers Flask to set the appropriate `Vary: Cookie` header and prepare session cookies before the headers are flushed to the client.
3. **WSGI Server Buffering**:
Some WSGI servers or reverse proxies (like Nginx) buffer responses by default. If buffering is enabled, the client will not receive the data in real-time chunks. Ensure your server configuration has buffering disabled (e.g., setting the `X-Accel-Buffering: no` header for Nginx) when implementing real-time streaming.
YouTip