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

Configure Feed

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

ocaml-linkedin: apply dune fmt

Pure formatting changes from `dune fmt`: doc comment placement moves
from above the binding to below it for `type`s, multi-line `match`
expressions collapse onto one line where they fit, and infix operator
applications pick up spaces (`Soup.($?)` -> `Soup.( $? )`). No
semantic changes.

+42 -22
+35 -22
README.md
··· 13 13 - **bytesrw integration**: `Bytes.Reader.t` / `Bytes.Writer.t` for streaming I/O 14 14 - **67 tests** covering spec examples, edge cases, incremental parsing, round-trips 15 15 16 - ## Install 16 + ## Installation 17 + 18 + Install with opam: 17 19 20 + ```sh 21 + $ opam install sse 18 22 ``` 19 - opam install sse 23 + 24 + If opam cannot find the package, it may not yet be released in the public 25 + `opam-repository`. Add the overlay repository, then install it: 26 + 27 + ```sh 28 + $ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git 29 + $ opam update 30 + $ opam install sse 20 31 ``` 21 32 22 33 ## Usage ··· 24 35 ### Client (parsing) 25 36 26 37 ```ocaml 27 - let parser = Sse.Parser.create () in 28 - let events = Sse.Parser.feed parser "data:hello\n\ndata:world\n\n" in 29 - List.iter (fun e -> print_endline e.Sse.data) events 38 + let parser = Sse.Parser.create () 39 + let events = Sse.Parser.feed parser "data:hello\n\ndata:world\n\n" 40 + let () = List.iter (fun e -> print_endline e.Sse.data) events 30 41 (* hello *) 31 42 (* world *) 32 43 ``` ··· 34 45 Incremental parsing (chunked HTTP responses, streaming): 35 46 36 47 ```ocaml 37 - let parser = Sse.Parser.create () in 38 - let _ = Sse.Parser.feed parser "data:hel" in (* partial — no events yet *) 39 - let events = Sse.Parser.feed parser "lo\n\n" in (* completed — dispatches *) 48 + let parser = Sse.Parser.create () 49 + (* partial chunk - no events yet *) 50 + let _ = Sse.Parser.feed parser "data:hel" 51 + (* completed chunk - dispatches *) 52 + let events = Sse.Parser.feed parser "lo\n\n" 40 53 (* events = [{ data = "hello"; ... }] *) 41 54 ``` 42 55 43 56 With bytesrw: 44 57 45 58 ```ocaml 46 - let parser = Sse.Parser.create () in 47 - let reader = Bytes.Reader.of_string "data:hello\n\n" in 48 - let events = Sse.Parser.read parser reader in 59 + let parser = Sse.Parser.create () 60 + let reader = Bytes.Reader.of_string "data:hello\n\n" 61 + let events = Sse.Parser.read parser reader 49 62 ``` 50 63 51 64 Reconnection (Last-Event-ID): 52 65 53 66 ```ocaml 54 - (* After disconnect, create new parser with last known ID *) 55 - let parser = Sse.Parser.create ~last_event_id:"42" () in 56 - (* Send Last-Event-ID: 42 header when reconnecting *) 67 + (* After disconnect, create new parser with last known ID. 68 + Send Last-Event-ID: 42 header when reconnecting. *) 69 + let parser = Sse.Parser.create ~last_event_id:"42" () 57 70 ``` 58 71 59 72 ### Server (serializing) 60 73 61 74 ```ocaml 62 - Sse.Serializer.event "hello" 63 - (* "data:hello\n\n" *) 75 + # Sse.Serializer.event "hello";; 76 + - : string = "data:hello\n\n" 64 77 65 - Sse.Serializer.event ~event:"update" ~id:"42" "payload" 66 - (* "event:update\ndata:payload\nid:42\n\n" *) 78 + # Sse.Serializer.event ~event:"update" ~id:"42" "payload";; 79 + - : string = "event:update\ndata:payload\nid:42\n\n" 67 80 68 - Sse.Serializer.event "line1\nline2" 69 - (* "data:line1\ndata:line2\n\n" *) 81 + # Sse.Serializer.event "line1\nline2";; 82 + - : string = "data:line1\ndata:line2\n\n" 70 83 71 - Sse.Serializer.comment "keepalive" 72 - (* ":keepalive\n" *) 84 + # Sse.Serializer.comment "keepalive";; 85 + - : string = ":keepalive\n" 73 86 ``` 74 87 75 88 HTTP headers for SSE responses:
+4
dune
··· 1 1 (env 2 2 (dev 3 3 (flags :standard %{dune-warnings}))) 4 + 5 + (mdx 6 + (files README.md) 7 + (libraries sse))
+2
dune-project
··· 1 1 (lang dune 3.21) 2 + (using mdx 0.4) 2 3 3 4 (name sse) 4 5 ··· 27 28 dune 28 29 (bytesrw (>= 0.1)) 29 30 (alcotest :with-test) 31 + (mdx :with-test) 30 32 fmt))
+1
sse.opam
··· 18 18 "dune" {>= "3.21"} 19 19 "bytesrw" {>= "0.1"} 20 20 "alcotest" {with-test} 21 + "mdx" {with-test} 21 22 "fmt" 22 23 "odoc" {with-doc} 23 24 ]