mirror of
https://github.com/aantron/dream.git
synced 2025-12-30 00:26:32 -05:00
Document example/w-server-sent-events
This commit is contained in:
parent
f997718427
commit
12b7ba714b
@ -77,8 +77,8 @@ if something is missing!
|
||||
- [**`w-query`**](w-query#files) — reading URL query
|
||||
parameters.
|
||||
- [**`w-server-sent-events`**](w-server-sent-events#files) —
|
||||
the server side of JavaScript
|
||||
[`EventSource`](https://developer.mozilla.org/en-US/docs/Web/API/EventSource).
|
||||
[`EventSource`](https://developer.mozilla.org/en-US/docs/Web/API/EventSource),
|
||||
an older alternative to WebSockets.
|
||||
- [**`w-site-prefix`**](w-site-prefix#files) — a Web app
|
||||
running not at `/`.
|
||||
- [**`w-template-stream`**](w-template-stream#files) — writing
|
||||
|
||||
@ -2,11 +2,55 @@
|
||||
|
||||
<br>
|
||||
|
||||
**Next steps:**
|
||||
In [server-sent
|
||||
events](https://developer.mozilla.org/en-US/docs/Web/API/EventSource), a client
|
||||
sends a request to a server, to which the server responds with header
|
||||
`Content-Type: text/event-stream`, and gradually streams events.
|
||||
|
||||
This example sets up a message-generating loop, `message_loop`, to simulate
|
||||
messages sent by other clients:
|
||||
|
||||
```ocaml
|
||||
let rec message_loop () =
|
||||
let%lwt () = Lwt_unix.sleep (Random.float 2.) in
|
||||
|
||||
incr last_message;
|
||||
let message = string_of_int !last_message in
|
||||
Dream.log "Generated message %s" message;
|
||||
|
||||
server_state := message::!server_state;
|
||||
!notify ();
|
||||
|
||||
message_loop ()
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
[Up to the example index](../#readme)
|
||||
When a client connects to the example's server-sent events endpoint at
|
||||
[http://localhost:8080/push](http://localhost:8080/push), the server first sends
|
||||
any messages that have already accumulated, and then gradually
|
||||
[streams](https://aantron.github.io/dream/#streaming) more messages as they are
|
||||
created.
|
||||
|
||||
You can see this in action either by visiting the endpoint directly, or as
|
||||
interpreted by the page at [http://localhost:8080](http://localhost:8080), which
|
||||
uses the browser
|
||||
[`EventSource`](https://developer.mozilla.org/en-US/docs/Web/API/EventSource)
|
||||
interface to server-sent events.
|
||||
|
||||
<br>
|
||||
|
||||
**See also:**
|
||||
|
||||
- [**`k-websocket`**](../k-websocket#files) for WebSockets, which largely
|
||||
supersede server-sent events.
|
||||
- [**`w-template-stream`**](../w-template-stream#files) for another example of
|
||||
“real-time” streaming with
|
||||
[`Dream.flush`](https://aantron.github.io/dream/#val-flush).
|
||||
|
||||
<br>
|
||||
|
||||
[Up to the example index](../#examples)
|
||||
|
||||
<!-- TODO OWASP link; injection general link. -->
|
||||
<!-- TODO Link to template syntax reference. -->
|
||||
|
||||
@ -28,13 +28,40 @@ let last_message =
|
||||
|
||||
let rec message_loop () =
|
||||
let%lwt () = Lwt_unix.sleep (Random.float 2.) in
|
||||
|
||||
incr last_message;
|
||||
let message = string_of_int !last_message in
|
||||
Dream.log "Generated message %s" message;
|
||||
|
||||
server_state := message::!server_state;
|
||||
!notify ();
|
||||
|
||||
message_loop ()
|
||||
|
||||
let rec forward_messages response =
|
||||
let%lwt messages =
|
||||
match !server_state with
|
||||
| [] ->
|
||||
let on_message, notify_message = Lwt.wait () in
|
||||
notify := Lwt.wakeup_later notify_message;
|
||||
let%lwt () = on_message in
|
||||
notify := ignore;
|
||||
Lwt.return !server_state
|
||||
| messages ->
|
||||
Lwt.return messages
|
||||
in
|
||||
|
||||
server_state := [];
|
||||
|
||||
messages
|
||||
|> List.rev
|
||||
|> List.map (Printf.sprintf "data: %s\n\n")
|
||||
|> String.concat ""
|
||||
|> fun text ->
|
||||
let%lwt () = Dream.write text response in
|
||||
let%lwt () = Dream.flush response in
|
||||
forward_messages response
|
||||
|
||||
let () =
|
||||
Lwt.async message_loop;
|
||||
|
||||
@ -45,28 +72,6 @@ let () =
|
||||
Dream.get "/" (fun _ -> Dream.respond home);
|
||||
|
||||
Dream.get "/push" (fun _ ->
|
||||
let rec forward_messages response =
|
||||
let%lwt messages =
|
||||
match !server_state with
|
||||
| [] ->
|
||||
let on_message, notify_message = Lwt.wait () in
|
||||
notify := Lwt.wakeup_later notify_message;
|
||||
let%lwt () = on_message in
|
||||
notify := ignore;
|
||||
Lwt.return !server_state
|
||||
| messages ->
|
||||
Lwt.return messages
|
||||
in
|
||||
server_state := [];
|
||||
messages
|
||||
|> List.rev
|
||||
|> List.map (Printf.sprintf "data: %s\n\n")
|
||||
|> String.concat ""
|
||||
|> fun text ->
|
||||
let%lwt () = Dream.write text response in
|
||||
let%lwt () = Dream.flush response in
|
||||
forward_messages response
|
||||
in
|
||||
Dream.stream
|
||||
~headers:["Content-Type", "text/event-stream"]
|
||||
forward_messages);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user