Browse Source

Fix explicit null data in server-sent events

pull/15789/head
fraggynikita 1 month ago
parent
commit
622beecc4e
  1. 2
      fastapi/routing.py
  2. 3
      fastapi/sse.py
  3. 14
      tests/test_sse.py

2
fastapi/routing.py

@ -514,7 +514,7 @@ def get_request_handler(
# validation (the user may mix types intentionally).
if item.raw_data is not None:
data_str: str | None = item.raw_data
elif item.data is not None:
elif item.data is not None or "data" in item.model_fields_set:
if hasattr(item.data, "model_dump_json"):
data_str = item.data.model_dump_json()
else:

3
fastapi/sse.py

@ -147,7 +147,8 @@ class ServerSentEvent(BaseModel):
@model_validator(mode="after")
def _check_data_exclusive(self) -> "ServerSentEvent":
if self.data is not None and self.raw_data is not None:
data_is_set = self.data is not None or "data" in self.model_fields_set
if data_is_set and self.raw_data is not None:
raise ValueError(
"Cannot set both 'data' and 'raw_data' on the same "
"ServerSentEvent. Use 'data' for JSON-serialized payloads "

14
tests/test_sse.py

@ -74,6 +74,11 @@ async def sse_items_string():
yield ServerSentEvent(data="plain text data")
@app.get("/items/stream-null", response_class=EventSourceResponse)
async def sse_items_null():
yield ServerSentEvent(data=None)
@app.post("/items/stream-post", response_class=EventSourceResponse)
async def sse_items_post() -> AsyncIterable[Item]:
for item in items:
@ -216,6 +221,12 @@ def test_string_data_json_encoded(client: TestClient):
assert 'data: "plain text data"\n' in response.text
def test_null_data_json_encoded(client: TestClient):
response = client.get("/items/stream-null")
assert response.status_code == 200
assert response.text == "data: null\n\n"
def test_server_sent_event_null_id_rejected():
with pytest.raises(ValueError, match="null"):
ServerSentEvent(data="test", id="has\0null")
@ -263,6 +274,9 @@ def test_data_and_raw_data_mutually_exclusive():
with pytest.raises(ValueError, match="Cannot set both"):
ServerSentEvent(data="json", raw_data="raw")
with pytest.raises(ValueError, match="Cannot set both"):
ServerSentEvent(data=None, raw_data="raw")
def test_sse_on_router_included_in_app(client: TestClient):
response = client.get("/api/events")

Loading…
Cancel
Save