Goal#
Implement the EventSource interface for consuming text/event-stream server pushes, including automatic reconnection and event ID tracking.
Depends on: "Integrate Streams API with fetch: Response.body and streaming Request bodies" (uses streaming HTTP responses).
Scope#
text/event-streamparser (WHATWG HTML §9.2.6)- Fields:
data:,event:,id:,retry:, comments (:prefix) - Multi-line
data:accumulates with a newline separator - Event dispatch on blank line; reset buffers between events
id:field updates the connection'slastEventId; an explicitid:with no value clears it; anid:field containing a NUL byte is ignoredretry:field updates the reconnection time (must be a non-negative integer of milliseconds)- Decoder: UTF-8 with replacement, tolerant of CR/LF/CRLF line endings
- Fields:
EventSourceinterfacenew EventSource(url, { withCredentials = false }?)- Properties:
url,readyState(CONNECTING = 0,OPEN = 1,CLOSED = 2),withCredentials close()permanently closes the connectiononopen,onmessage,onerrorplusaddEventListenerequivalents- Custom event types via the
event:field are dispatched as their own type
- HTTP behaviour
- Request:
Accept: text/event-stream,Cache-Control: no-store, sendLast-Event-IDheader on reconnect when one is known - Reject non-
text/event-streamresponses with aCLOSEDfailure (no reconnect) - On network error or successful close, schedule a reconnect with the current retry timeout (default 3 s, capped to a reasonable maximum)
- 204 / 401 / 403 / 404 / 410 / 5xx and many other non-2xx statuses follow the spec's reconnect-or-fail rules — implement the failure case (no reconnect) per spec for the obvious terminal codes
- CORS: respect
withCredentials, sendOrigin, acceptAccess-Control-Allow-Origin/Access-Control-Allow-Credentials
- Request:
- Lifecycle
- GC root active
EventSourceinstances similar toWebSocket
- GC root active
Acceptance Criteria#
- Connects to a
text/event-streamendpoint and dispatchesmessageevents as the server pushes data - Multi-line
data:blocks are joined with\\n event: foo\\ndata: x\\n\\ndispatches a customfooevent withdata === 'x'- After a server disconnect, the client reconnects automatically using the configured retry timeout and sends
Last-Event-ID close()ends the connection and prevents further reconnects- Cross-origin requests with
withCredentials: falsesucceed only when the server returns the required CORS headers - Unit tests for parser edge cases (CR/LF/CRLF mixing, multi-line data, retry parsing, NUL in id, comments) + an integration test against an in-process SSE server
- Conventions
cargo fmt --all --checkcargo clippy --workspace -- -D warningscargo test --workspace