sse
stableParse and format Server-Sent Events (SSE) streams according to the W3C specification, including event formatting, stream parsing, keepalives, and HTTP header generation.
use plugin sse::{parse_event, format_event, parse_stream, …} Functions (12)
- parse_event Parse a single SSE event block into a table
- format_event Format data as an SSE event string
- parse_stream Parse a full SSE stream into a table of events
- format_comment Format a comment line for an SSE stream
- format_retry Format a retry directive in milliseconds
- format_keepalive Return the SSE keepalive ping string
- format_data_only Format data-only lines without an event type
- validate_event_type Check whether an event type string is valid
- extract_last_event_id Extract the last event ID from a raw stream
- build_headers Build HTTP request headers for SSE connections
- event_count Count the number of events in a raw stream
- content_type Return the SSE content-type string
Overview
sse is a stateless toolkit for the wire format behind Server-Sent Events: the
plain-text protocol where a server streams field: value lines and clients
listen over a long-lived HTTP connection. Every function is a pure transform on
strings — there is no socket, connection object, or hidden state to manage. You
either parse raw stream text into ordinary tables (parse_event, parse_stream,
extract_last_event_id, event_count) or build spec-compliant output to write
to a response (format_event, format_comment, format_retry,
format_keepalive, format_data_only).
The mental model is two halves that mirror each other: a parsing half that turns
the text/event-stream wire format into Zolo values, and a formatting half that
turns Zolo values back into bytes. Reach for it on the server when emitting a
stream (set the content_type, format each event, send format_keepalive
periodically), and on the client when consuming one (build request headers with
build_headers, then parse incoming chunks and resume from
extract_last_event_id after a drop).
Common patterns
Emit a stream: set the content type, then format each event before writing it:
use plugin sse::{content_type, format_event}
print("Content-Type: {content_type()}")
print(format_event("system online", "status", "1"))
print(format_event("user joined", "presence", "2"))
Consume a stream: parse every event, then remember where to resume after a drop:
use plugin sse::{parse_stream, extract_last_event_id}
let raw = "event: tick\ndata: 1\nid: 1\n\nevent: tick\ndata: 2\nid: 2\n\n"
let events = parse_stream(raw)
for _, evt in events {
print("{evt["event"]}: {evt["data"]}")
}
print("resume after: {extract_last_event_id(raw)}")
Open a client connection that resumes from the last seen id, then keep it warm:
use plugin sse::{build_headers, format_keepalive}
let headers = build_headers("42")
for key, val in headers {
print("{key}: {val}")
}
print("keepalive: {format_keepalive()}")
Parse a single SSE event block into a table
Parses a single SSE event block (multiple field: value lines) and returns a table with event, data, id, and retry. The event field defaults to "message" if not specified.
use plugin sse::{parse_event}
let raw = "event: update\ndata: hello world\nid: 42\n"
let evt = parse_event(raw)
print("type={evt["event"]} data={evt["data"]} id={evt["id"]}")
A retry: line is parsed into an integer, and a missing event defaults to
"message":
use plugin sse::{parse_event}
let evt = parse_event("data: keepalive\nretry: 3000\n")
print("event={evt["event"]} retry={evt["retry"]}")
Format data as an SSE event string
Formats an SSE event string ready to write to an HTTP response. event_type and id are optional. The default event type ("message") is omitted from the output per spec.
use plugin sse::{format_event}
let msg = format_event("hello world", "update", "1")
print(msg)
let simple = format_event("ping", nil, nil)
print(simple)
Multi-line data is split into one data: line per source line, which the
client reassembles into a single payload joined by newlines:
use plugin sse::{format_event}
let block = format_event("first line\nsecond line", "log", "7")
print(block)
Parse a full SSE stream into a table of events
Parses a complete SSE stream (multiple events separated by blank lines) and returns a table of event tables, each with event, data, id, and retry.
use plugin sse::{parse_stream}
let stream = "data: first\n\ndata: second\nid: 2\n\n"
let events = parse_stream(stream)
for _, evt in events {
print(evt["data"])
}
Pair it with event_count to size a stream before walking it:
use plugin sse::{parse_stream, event_count}
let raw = "data: a\n\ndata: b\n\ndata: c\n\n"
print("parsing {event_count(raw)} events")
let events = parse_stream(raw)
print("got {#events} tables")
Format a comment line for an SSE stream
Formats one or more lines as SSE comments (prefixed with :). Comments are ignored by clients but keep the connection alive.
use plugin sse::{format_comment}
let c = format_comment("server time: 12:00")
print(c)
Format a retry directive in milliseconds
Formats a retry: directive telling the client to wait ms milliseconds before reconnecting after a dropped connection.
use plugin sse::{format_retry}
let directive = format_retry(5000)
print(directive)
Return the SSE keepalive ping string
Returns the SSE keepalive string (":\n\n"). Send this periodically to prevent proxies and clients from closing an idle connection.
use plugin sse::{format_keepalive}
let ping = format_keepalive()
print(ping)
Format data-only lines without an event type
Formats multi-line data as SSE data: lines without setting an event type. Each line of data becomes a separate data: field.
use plugin sse::{format_data_only}
let msg = format_data_only("line one\nline two")
print(msg)
Check whether an event type string is valid
Returns true if event_type is a valid SSE event type name (non-empty, no newlines or colons).
use plugin sse::{validate_event_type}
print(validate_event_type("update"))
print(validate_event_type("bad:type"))
print(validate_event_type(""))
Extract the last event ID from a raw stream
Scans a raw SSE stream and returns the value of the last id: field found (a string), or nil if none. Use this to resume a stream from where it left off.
use plugin sse::{extract_last_event_id}
let stream = "id: 1\ndata: a\n\nid: 2\ndata: b\n\n"
let last_id = extract_last_event_id(stream)
print("resume from id: {last_id}")
Build HTTP request headers for SSE connections
Returns a table of HTTP request headers appropriate for opening an SSE connection: Accept, Cache-Control, and Connection. If last_event_id is non-empty, a Last-Event-ID header is also included for stream resumption.
use plugin sse::{build_headers}
let headers = build_headers("42")
for key, val in headers {
print("{key}: {val}")
}
On a fresh connection with no prior id, pass nil to omit Last-Event-ID:
use plugin sse::{build_headers}
let headers = build_headers(nil)
for key, val in headers {
print("{key}: {val}")
}
Count the number of events in a raw stream
Counts the number of events in a raw SSE stream by counting non-comment data blocks separated by blank lines.
use plugin sse::{event_count}
let stream = "data: one\n\ndata: two\n\ndata: three\n\n"
print("events: {event_count(stream)}")
Return the SSE content-type string
Returns the correct MIME type string for SSE responses: "text/event-stream".
use plugin sse::{content_type}
print(content_type())