Server-Sent Events (SSE) parser and serializer
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

OCaml 93.3%
Dune 2.3%
Other 4.5%
16 1 0

Clone this repository

https://tangled.org/gazagnaire.org/ocaml-sse https://tangled.org/did:plc:jhift2vwcxhou52p3sewcrpx/ocaml-sse
git@git.recoil.org:gazagnaire.org/ocaml-sse git@git.recoil.org:did:plc:jhift2vwcxhou52p3sewcrpx/ocaml-sse

For self-hosted knots, clone URLs may differ based on your setup.

Download tar.gz
README.md

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.t for 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