Server-Sent Events (SSE)
Relevant source files
The following files were used as context for generating this wiki page:
Server-Sent Events (SSE) in the HXLibs project enable a server to push real-time updates to web clients over a single, long-lived HTTP connection. The system provides both a C++ implementation within the HX::net namespace for high-performance server-side streaming and a Python-based test server for validating client interactions.
The C++ implementation utilizes coroutines to handle asynchronous event streaming without blocking the underlying I/O. It supports standard SSE features including custom event types, data payloads, event IDs for reconnection, and retry intervals.
Sources: include/HXLibs/net/protocol/http/Response.hpp:46-100, tests/net/client/sse/sse_server.py:84-135
Data Structures and Protocols
The project defines specific structures to represent SSE events and the required HTTP headers for the text/event-stream protocol.
SseEvent Structure
The SseEvent struct encapsulates the components of a single SSE message.
| Field | Type | Description |
|---|---|---|
data | std::string | The message payload. |
event | std::string | The specific name of the event type. |
id | std::optional<std::string> | A unique identifier for the event. |
retry | std::optional<std::chrono::milliseconds> | Reconnection delay instruction for the client. |
Sources: include/HXLibs/net/protocol/http/Http.hpp:117-127
Protocol Requirements
To establish an SSE stream, the server must set specific HTTP headers to prevent caching and buffering.
- Content-Type: Must be
text/event-stream. - Cache-Control: Should be
no-cache. - Connection: Must be
keep-alive. - X-Accel-Buffering: Often set to
noto bypass proxy buffering.
Sources: tests/net/client/sse/sse_server.py:141-144, include/HXLibs/net/protocol/http/Response.hpp:438-440
Server-Side Architecture
The server-side implementation revolves around the HttpResponse class and a specialized SseStream helper.
Event Streaming Flow
The HttpResponse::makeSseStream() function initializes the connection by sending the initial 200 OK status and required headers. Once established, the SseStream provides methods to push events to the client.
SseStream Implementation
The SseStream class provides two primary methods for communication:
- ping(): Sends a comment line (
:ping\n\n) to keep the connection alive. - push(SseEvent): Serializes an
SseEventinto the wire format and sends it through the underlyingHttpIO.
Sources: include/HXLibs/net/protocol/http/Response.hpp:56-82
Wire Format Serialization
The serialization logic ensures that multi-line data is correctly prefixed with the data: tag, and that all fields are terminated by the required newline characters.
// Wire format example
// Source: include/HXLibs/net/protocol/http/Response.hpp:84-100
coroutine::Task<> sendStr(std::string_view key, std::string_view val) {
using namespace std::string_view_literals;
auto& io = _res.getIO();
auto pos = val.find('\n');
for (;;) {
co_await io.fullySend(key);
if (pos == std::string_view::npos) {
co_await io.fullySend(val);
co_await io.fullySend("\n"sv);
break;
} else {
auto _ = val.substr(0, pos);
co_await io.fullySend(_);
co_await io.fullySend("\n"sv);
}
val = val.substr(pos + 1);
pos = val.find('\n');
}
}
The wire format follows the standard pattern:
event: [type]\ndata: [line1]\ndata: [line2]\nid: [identifier]\nretry: [milliseconds]\n\n(Double newline to terminate the event)
Sources: include/HXLibs/net/protocol/http/Response.hpp:64-82, tests/net/client/sse/sse_server.py:65-81
Client-Side Reception
The HttpResponse class includes a parserSseStrem() method that allows a C++ client to asynchronously consume SSE events using a coroutine co_yield pattern.
Parsing Logic
- Validation: The client checks that the status code is
200and theContent-Typecontainstext/event-stream. - Buffering: Data is received into a buffer.
- Field Extraction: The parser identifies keys (e.g.,
data,event,id) by locating the colon (:) separator. - Yielding: Complete events are yielded to the caller.
Summary
The Server-Sent Events implementation in HXLibs provides a efficient, coroutine-based mechanism for unidirectional real-time communication. By adhering to the text/event-stream standard, it remains compatible with standard web browsers while offering a C++ interface for both server-side broadcasting and client-side consumption.
Sources: include/HXLibs/net/protocol/http/Response.hpp:184-232, tests/net/client/sse/sse_server.py:84-135