I am working on a FastAPI application where I need to set an HTTP cookie while streaming data to the client using Server-Sent Events (SSE). However, I am encountering an issue where the cookie is not being set in the client browser when I use response.set_cookie
inside the FastAPI route that returns the StreamingResponse.
from fastapi import FastAPI, Response, Request
from starlette.responses import StreamingResponse
app = FastAPI()
@app.get("/stream")
async def stream(response: Response, request: Request):
# Example function to handle session management
user_chat_session = handle_session(request, response, redis_client)
# Attempt to set a cookie
response.set_cookie(
key="chat_session",
value="test",
httponly=True,
expires=3600, # 1-hour expiration
)
# Return a streaming response for SSE
return StreamingResponse(
chat_client.stream(question="hello", user_chat_session=user_chat_session),
media_type="text/event-stream"
)
The cookie chat_session is not being set on the client side. I understand that response.set_cookie modifies the HTTP headers, and I suspect this issue might be related to how StreamingResponse works.
Since SSE uses a streaming connection, the response headers are sent immediately, and once the headers are sent, it’s no longer possible to modify them (which is likely why set_cookie isn’t taking effect).
If I remove the StreamingResponse
and instead return a normal response (like return {"message": "test"}
), the cookie is set correctly. This makes me believe the issue is specific to StreamingResponse
and how it handles response headers in an SSE setup.
Is it possible to set cookies while also sending a StreamingResponse
in FastAPI?
If not, what would be the best workaround?
Any insights, suggestions, or best practices on handling cookies in combination with SSE would be greatly appreciated!
Calling response.set_cookie
before returning the StreamingResponse
.
Confirmed that cookies are set correctly when the route returns a regular JSON response (so the issue only occurs when using StreamingResponse
).
You have set the cookie on the wrong response. Please update your code as follows, and it will work correctly.
@app.get("/stream")
async def stream(response: Response, request: Request):
# Example function to handle session management
user_chat_session = handle_session(request, response, redis_client)
# Return a streaming response for SSE
streaming_response = StreamingResponse(
chat_client.stream(question="hello", user_chat_session=user_chat_session),
media_type="text/event-stream"
)
# Set a cookie
streaming_response.set_cookie(
key="chat_session",
value="test",
httponly=True,
expires=3600, # 1-hour expiration
)
return streaming_response