@@ -33,10 +33,20 @@ class EventSourceResponse(StreamingResponse):
3333 media_type = "text/event-stream"
3434
3535
36- def _check_id_no_null (v : str | None ) -> str | None :
36+ def _check_single_line (v : str | None , field_name : str ) -> str | None :
37+ if v is not None and ("\r " in v or "\n " in v ):
38+ raise ValueError (f"SSE '{ field_name } ' must be a single line" )
39+ return v
40+
41+
42+ def _check_event_single_line (v : str | None ) -> str | None :
43+ return _check_single_line (v , "event" )
44+
45+
46+ def _check_id_valid (v : str | None ) -> str | None :
3747 if v is not None and "\0 " in v :
3848 raise ValueError ("SSE 'id' must not contain null characters" )
39- return v
49+ return _check_single_line ( v , "id" )
4050
4151
4252class ServerSentEvent (BaseModel ):
@@ -86,24 +96,27 @@ class ServerSentEvent(BaseModel):
8696 ] = None
8797 event : Annotated [
8898 str | None ,
99+ AfterValidator (_check_event_single_line ),
89100 Doc (
90101 """
91102 Optional event type name.
92103
93104 Maps to `addEventListener(event, ...)` on the browser. When omitted,
94- the browser dispatches on the generic `message` event.
105+ the browser dispatches on the generic `message` event. Must be a
106+ single line.
95107 """
96108 ),
97109 ] = None
98110 id : Annotated [
99111 str | None ,
100- AfterValidator (_check_id_no_null ),
112+ AfterValidator (_check_id_valid ),
101113 Doc (
102114 """
103115 Optional event ID.
104116
105117 The browser sends this value back as the `Last-Event-ID` header on
106- automatic reconnection. **Must not contain null (`\\ 0`) characters.**
118+ automatic reconnection. **Must be a single line** and must not contain
119+ null (`\\ 0`) characters.
107120 """
108121 ),
109122 ] = None
0 commit comments