mirror of
https://github.com/aantron/dream.git
synced 2025-10-02 00:03:57 -04:00
r-template-stream
When a client connects to this Web app, it sends back one paragraph per second in a response stream:
let render = response => {
%% response
<html>
<body>
% let rec paragraphs = index => {
<p><%i index %></p>
% let%lwt () = Dream.flush(response);
% let%lwt () = Lwt_unix.sleep(1.);
% paragraphs(index + 1);
% };
% let%lwt () = paragraphs(0);
</body>
</html>
};
let () =
Dream.run
@@ Dream.logger
@@ _ => Dream.stream(~headers=[("Content-Type", Dream.text_html)], render);
$ cd example/r-template-stream
$ npm install esy && npx esy
$ npx esy start
Visit http://localhost:8080 [playground] to see it in action.
The important differences with regular usage of templates are:
- We create the response with
Dream.stream
, which is a convenience wrapper around some lower-level functions that would prepare a response for streaming. - We use the opening line
%% response
to tell the templater that we don't want to build a string, but to stream the template to a response in scope under the nameresponse
. - We use the promise library Lwt inside the
template for asynchronous control flow. See example
5-promise
for an introduction to Lwt.
The call to Dream.flush
isn't
necessary in most real-world cases — Dream's HTTP layer automatically
schedules the writing of data. However, this example is trying to appear
interactive, so we force writing of all output after generating each <p>
tag.
See also:
r-template
for the simpler way to do templates, building up entire bodies as strings.7-template
section Security for XSS prevention considerations.w-template-stream
is the OCaml version of this example.