ocaml-sse#
Pure OCaml Server-Sent Events (SSE) parser and serializer.
Features#
- Spec-compliant parser per WHATWG HTML Living Standard §9.2
- Incremental: feed chunks of any size, get events out — handles partial lines across chunks
- All line endings: LF, CR, CRLF, and mixed
- Full field support:
data(multi-line),event,id(with NULL rejection),retry, comments - BOM stripping on first chunk
- Serializer for server-side event streams
- bytesrw integration:
Bytes.Reader.t/Bytes.Writer.tfor streaming I/O - 67 tests covering spec examples, edge cases, incremental parsing, round-trips
Installation#
Install with opam:
$ opam install sse
If opam cannot find the package, it may not yet be released in the public
opam-repository. Add the overlay repository, then install it:
$ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git
$ opam update
$ opam install sse
Usage#
Client (parsing)#
let parser = Sse.Parser.create ()
let events = Sse.Parser.feed parser "data:hello\n\ndata:world\n\n"
let () = List.iter (fun e -> print_endline e.Sse.data) events
(* hello *)
(* world *)
Incremental parsing (chunked HTTP responses, streaming):
let parser = Sse.Parser.create ()
(* partial chunk - no events yet *)
let _ = Sse.Parser.feed parser "data:hel"
(* completed chunk - dispatches *)
let events = Sse.Parser.feed parser "lo\n\n"
(* events = [{ data = "hello"; ... }] *)
With bytesrw:
let parser = Sse.Parser.create ()
let reader = Bytesrw.Bytes.Reader.of_string "data:hello\n\n"
let events = Sse.Parser.read parser reader
Reconnection (Last-Event-ID):
(* After disconnect, create new parser with last known ID.
Send Last-Event-ID: 42 header when reconnecting. *)
let parser = Sse.Parser.create ~last_event_id:"42" ()
Server (serializing)#
# Sse.Serializer.event "hello";;
- : string = "data:hello\n\n"
# Sse.Serializer.event ~event:"update" ~id:"42" "payload";;
- : string = "event:update\ndata:payload\nid:42\n\n"
# Sse.Serializer.event "line1\nline2";;
- : string = "data:line1\ndata:line2\n\n"
# Sse.Serializer.comment "keepalive";;
- : string = ":keepalive\n"
HTTP headers for SSE responses:
let headers = Sse.Serializer.headers
(* [("Content-Type", "text/event-stream");
("Cache-Control", "no-cache");
("Connection", "keep-alive")] *)
Spec#
Implements the event stream format from the WHATWG HTML Living Standard §9.2.
License#
ISC