cwist
Modern C web framework with libttak runtime
Loading...
Searching...
No Matches
Server-Sent Events API

Header: <cwist/net/http/sse.h>

Helpers for sending text/event-stream data. There are two ways to use them:

  • Response mode (cwist_sse_response_*): frames are appended to the response body of an ordinary handler. The response is sent when the handler returns, so this suits a fixed batch of events.
  • Stream mode (cwist_sse_stream_*): the headers are written to the client socket immediately, and each event is sent as soon as it is written. This suits events produced over time.

Most functions return a cwist_error_t. A call that is rejected for a bad argument (a NULL pointer, or retry_ms below -1) or fails to build the frame returns err_i16 == -1. The tests check success with err.error.err_i16 == 0.

Every event is written as lines of the form field:value followed by a blank line. The fields appear in the order id, event, retry, data. A NULL event or id is omitted. A data string that contains newlines is split into one data: line per line, and a NULL data produces an empty data: line. There is no space after the colon, so the event ("update", "42", 1500, "first\nsecond") is sent as:

id:42
event:update
retry:1500
data:first
data:second

Types

cwist_sse_event_t

typedef struct cwist_sse_event {
const char *event;
const char *id;
int retry_ms;
const char *data;
struct cwist_sse_event cwist_sse_event_t
const char * id
Definition sse.h:16
int retry_ms
Definition sse.h:17
const char * data
Definition sse.h:18
const char * event
Definition sse.h:15

A structured event for cwist_sse_response_write and cwist_sse_stream_write. NULL fields are omitted. retry_ms is sent when it is 0 or greater and omitted when it is -1.

cwist_sse_stream_t

An opaque handle for an open stream, created by cwist_sse_stream_open.

Response mode

cwist_sse_response_init

cwist_error_t cwist_sse_response_init(cwist_http_response *res)
Prepare a response buffer for a Server-Sent Events reply.
Definition sse.c:117
Integrated error structure used throughout the system.
Definition cwist_err.h:72
HTTP Response Object. Supports standard string body or Zero-Copy pointer body.
Definition http.h:82

Adds the SSE headers to res and sets res->keep_alive to true. The headers are:

Header Value
Content-Type text/event-stream; charset=utf-8
Cache-Control no-cache
X-Accel-Buffering no

Returns err_i16 == -1 if res is NULL or a header cannot be added.

cwist_sse_response_event

const char *id, int retry_ms, const char *data);
cwist_error_t cwist_sse_response_event(cwist_http_response *res, const char *event, const char *id, int retry_ms, const char *data)
Append a formatted SSE event to a response buffer.
Definition sse.c:138

Appends one event to the response body. Pass NULL for event or id, and -1 for retry_ms, to leave that field out. A retry_ms below -1 is rejected with err_i16 == -1.

cwist_sse_response_write

const cwist_sse_event_t *event);
cwist_error_t cwist_sse_response_write(cwist_http_response *res, const cwist_sse_event_t *event)
Append an SSE event described by a cwist_sse_event_t to a response.
Definition sse.c:168

Same as cwist_sse_response_event, taking the fields from a cwist_sse_event_t. Returns err_i16 == -1 if event is NULL.

cwist_sse_response_comment

cwist_error_t cwist_sse_response_comment(cwist_http_response *res, const char *comment)
Append an SSE comment line to a response buffer.
Definition sse.c:154
size_t cap
Definition otel.c:56

Appends a comment line (:text) followed by a blank line. Clients ignore comments, so they are used as heartbeats to keep a connection open.

Stream mode

cwist_sse_stream_open

struct cwist_sse_stream cwist_sse_stream_t
Definition sse.h:11
cwist_sse_stream_t * cwist_sse_stream_open(cwist_http_request *req)
Upgrade a request connection to a live SSE stream.
Definition sse.c:205

Writes the 200 OK status line and the SSE headers to req->client_fd and sets req->upgraded. When the handler returns, the server sees req->upgraded, writes no response of its own, and does not keep the connection alive, so every event must be sent before the handler returns. Returns NULL if req is NULL, req->client_fd is negative, req->upgraded is already set, or the write fails.

cwist_sse_stream_send

const char *id, int retry_ms, const char *data);
cwist_error_t cwist_sse_stream_send(cwist_sse_stream_t *stream, const char *event, const char *id, int retry_ms, const char *data)
Send a formatted SSE event on a live stream.
Definition sse.c:233

Sends one event on the stream with the same field rules as cwist_sse_response_event. Writes are serialized with a mutex, so one stream can be used from several threads. If a write fails, the stream is marked closed and every later send on it returns err_i16 == -1.

cwist_sse_stream_write

const cwist_sse_event_t *event);
cwist_error_t cwist_sse_stream_write(cwist_sse_stream_t *stream, const cwist_sse_event_t *event)
Send an SSE event described by a cwist_sse_event_t on a stream.
Definition sse.c:273

Same as cwist_sse_stream_send, taking the fields from a cwist_sse_event_t.

cwist_sse_stream_comment

cwist_error_t cwist_sse_stream_comment(cwist_sse_stream_t *stream, const char *comment)
Send an SSE comment line on a live stream.
Definition sse.c:256

Sends a comment line on the stream, for example as a heartbeat.

cwist_sse_stream_close

void cwist_sse_stream_close(cwist_sse_stream_t *stream)
Close a live SSE stream and release its resources.
Definition sse.c:285

Frees the stream handle. It does not close the client socket. Passing NULL is allowed.

Convenience macros

Macro Expands to
CWIST_SSE_EVENT(payload) a cwist_sse_event_t with only data set
CWIST_SSE_NAMED(name, payload) a cwist_sse_event_t with event and data set
CWIST_SSE_JSON(payload) CWIST_SSE_NAMED("message", payload)
CWIST_SSE_RESPONSE_SEND(res, event) cwist_sse_response_write(res, &event)
CWIST_SSE_STREAM_SEND(stream, event) cwist_sse_stream_write(stream, &event)

The two SEND macros take the event as an lvalue because they take its address.

Example

A handler that sends a fixed batch of events (this is the pattern used by tutorial 08):

(void)req;
cwist_sse_response_event(res, "message", "1", -1, "Welcome to Live SSE Stream");
cwist_sse_response_event(res, "update", "2", -1, "Tick 1");
}

A handler that streams events directly to the socket. Events are sent while the handler is still running:

(void)res;
if (!stream) return;
cwist_sse_stream_comment(stream, "heartbeat");
}
#define CWIST_SSE_STREAM_SEND(stream, event)
Definition sse.h:42
#define CWIST_SSE_NAMED(event_name, payload)
Definition sse.h:38

See tests/test_sse.c for the exact output of each call.