diff --git a/example/README.md b/example/README.md
index 6853e51..2369d11 100644
--- a/example/README.md
+++ b/example/README.md
@@ -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
diff --git a/example/w-server-sent-events/README.md b/example/w-server-sent-events/README.md
index 546e64f..d9dab5e 100644
--- a/example/w-server-sent-events/README.md
+++ b/example/w-server-sent-events/README.md
@@ -2,11 +2,55 @@
-**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 ()
+```
-[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.
+
+
+
+**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).
+
+
+
+[Up to the example index](../#examples)
diff --git a/example/w-server-sent-events/server_sent_events.eml.ml b/example/w-server-sent-events/server_sent_events.eml.ml
index 9230f4e..91c5e8b 100644
--- a/example/w-server-sent-events/server_sent_events.eml.ml
+++ b/example/w-server-sent-events/server_sent_events.eml.ml
@@ -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);