ocaml http/1, http/2 and websocket client and server library
at main 2.0 kB view raw
1type event = { 2 event_type : string option; 3 data : string; 4 id : string option; 5 retry : int option; 6} 7 8let event data = { event_type = None; data; id = None; retry = None } 9 10let event_typed ~event_type data = 11 { event_type = Some event_type; data; id = None; retry = None } 12 13let make ?event_type ?id ?retry data = { event_type; data; id; retry } 14 15let format ev = 16 let buf = Buffer.create 64 in 17 let add_kv k v = 18 Buffer.add_string buf k; 19 Buffer.add_string buf ": "; 20 Buffer.add_string buf v; 21 Buffer.add_char buf '\n' 22 in 23 Option.iter (fun t -> add_kv "event" t) ev.event_type; 24 Option.iter (fun i -> add_kv "id" i) ev.id; 25 Option.iter 26 (fun r -> 27 Buffer.add_string buf "retry: "; 28 Buf.int buf r; 29 Buffer.add_char buf '\n') 30 ev.retry; 31 String.split_on_char '\n' ev.data 32 |> List.iter (fun line -> 33 Buffer.add_string buf "data: "; 34 Buffer.add_string buf line; 35 Buffer.add_char buf '\n'); 36 Buffer.add_char buf '\n'; 37 Buffer.contents buf 38 39let headers = 40 [ 41 ("content-type", "text/event-stream"); 42 ("cache-control", "no-cache"); 43 ("connection", "keep-alive"); 44 ("x-accel-buffering", "no"); 45 ] 46 47let respond generator = 48 let next () = 49 match generator () with 50 | None -> None 51 | Some ev -> Some (Cstruct.of_string (format ev)) 52 in 53 Response.stream ~headers next 54 55let respond_with_stream (events : event Eio.Stream.t) = 56 let next () = 57 try 58 let ev = Eio.Stream.take events in 59 Some (Cstruct.of_string (format ev)) 60 with _ -> None 61 in 62 Response.stream ~headers next 63 64let respond_raw generator = 65 let next () = 66 match generator () with 67 | None -> None 68 | Some s -> Some (Cstruct.of_string s) 69 in 70 Response.stream ~headers next 71 72let respond_raw_stream (strings : string Eio.Stream.t) = 73 let next () = 74 try 75 let s = Eio.Stream.take strings in 76 Some (Cstruct.of_string s) 77 with _ -> None 78 in 79 Response.stream ~headers next