Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
.PHONY : build

default:
@dune build

build :
@dune build -p dream-pure,dream-httpaf,dream --no-print-directory @install

Expand Down
2 changes: 0 additions & 2 deletions dream-httpaf.opam
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ depends: [
"dune" {>= "2.7.0"} # --instrument-with.
"lwt"
"lwt_ppx" {>= "1.2.2"}
"lwt_ssl"
"ocaml" {>= "4.08.0"}
"ssl" {>= "0.5.8"} # Ssl.get_negotiated_alpn_protocol.

# Currently vendored.
# "gluten"
Expand Down
1 change: 1 addition & 0 deletions dream-pure.opam
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ depends: [
"ocaml" {>= "4.08.0"}
"ptime" {>= "0.8.1"} # Ptime.weekday.
"uri" {>= "4.2.0"}
"eio" {>= "0.2"}

# Testing, development.
"alcotest" {with-test}
Expand Down
4 changes: 2 additions & 2 deletions dream.opam
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ depends: [
"graphql-lwt"
"lwt"
"lwt_ppx" {>= "1.2.2"}
"lwt_ssl"
"logs" {>= "0.5.0"}
"magic-mime"
"mirage-clock"
Expand All @@ -70,9 +69,10 @@ depends: [
"multipart_form" {>= "0.3.0"}
"ocaml" {>= "4.08.0"}
"ptime" {>= "0.8.1"} # Ptime.v.
"ssl" {>= "0.5.8"} # Ssl.get_negotiated_alpn_protocol.
"uri" {>= "4.2.0"}
"yojson" # ...
"eio_main" {>= "0.2"}
"lwt_eio" {>= "0.1"}

# Testing, development.
"alcotest" {with-test}
Expand Down
11 changes: 9 additions & 2 deletions example/1-hello/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ This project is so simple that it doesn't even log requests!

```ocaml
let () =
Dream.run (fun _ ->
Dream.html "Good morning, world!")
Eio_main.run (fun env ->
Dream.run env (fun _ ->
Dream.html "Good morning, world!")
)
```

<br>
Expand Down Expand Up @@ -39,6 +41,11 @@ name of the `.ml` file, but with `.ml` changed to `.exe`.

<br>

A Dream server runs in an [Eio](https://github.com/ocaml-multicore/eio) event loop,
which is created by `Eio_main.run`.

<br>

**Next steps:**

- The next example, [**`2-middleware`**](../2-middleware#files), adds a logger
Expand Down
6 changes: 4 additions & 2 deletions example/1-hello/hello.ml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
let () =
Dream.run (fun _ ->
Dream.html "Good morning, world!")
Eio_main.run (fun env ->
Dream.run env (fun _ ->
Dream.html "Good morning, world!")
)
10 changes: 6 additions & 4 deletions example/2-middleware/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ middlewares, the [*logger*](https://aantron.github.io/dream/#val-logger):

```ocaml
let () =
Dream.run
(Dream.logger (fun _ ->
Dream.html "Good morning, world!"))
Eio_main.run (fun env ->
Dream.run env
(Dream.logger (fun _ ->
Dream.html "Good morning, world!")))
```

<br>
Expand All @@ -25,7 +26,8 @@ in this example looks like this:

```ocaml
let () =
Dream.run
Eio_main.run @@ fun env ->
Dream.run env
@@ Dream.logger
@@ fun _ -> Dream.html "Good morning, world!"
```
Expand Down
3 changes: 2 additions & 1 deletion example/2-middleware/middleware.ml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
let () =
Dream.run
Eio_main.run @@ fun env ->
Dream.run env
@@ Dream.logger
@@ fun _ -> Dream.html "Good morning, world!"
3 changes: 2 additions & 1 deletion example/3-router/router.ml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
let () =
Dream.run
Eio_main.run @@ fun env ->
Dream.run env
@@ Dream.logger
@@ Dream.router [

Expand Down
3 changes: 2 additions & 1 deletion example/4-counter/counter.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ let count_requests inner_handler request =
inner_handler request

let () =
Dream.run
Eio_main.run @@ fun env ->
Dream.run env
@@ Dream.logger
@@ count_requests
@@ Dream.router [
Expand Down
57 changes: 11 additions & 46 deletions example/5-promise/README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
# `5-promise`

(note this example is now badly named, as it doesn't use any promises)

<br>

[**`4-counter`**](../4-counter#files) was limited to counting requests *before*
passing them on to the rest of the app. With the promise library
[Lwt](https://github.com/ocsigen/lwt), we can await responses, and do something
*after*. In this example, we separately count requests that were handled
successfully, and those that caused an exception:
passing them on to the rest of the app. We can also await responses, and do
something *after*. In this example, we separately count requests that were
handled successfully, and those that caused an exception:

```ocaml
let successful = ref 0
let failed = ref 0

let count_requests inner_handler request =
try%lwt
let%lwt response = inner_handler request in
try
let response = inner_handler request in
successful := !successful + 1;
Lwt.return response

response
with exn ->
failed := !failed + 1;
raise exn

let () =
Dream.run
Eio_main.run @@ fun env ->
Dream.run env
@@ Dream.logger
@@ count_requests
@@ Dream.router [
Expand All @@ -49,49 +50,13 @@ Try it in the [playground](http://dream.as/5-promise).

<br>

As you can see, the
[core constructs](https://ocsigen.org/lwt/latest/api/Ppx_lwt) of Lwt are:

- `let%lwt` to await the result of a promise.
- `try%lwt` to catch both exceptions and rejections. Lwt promises can only be
rejected with exceptions, of OCaml type `exn`.
- `Lwt.return` to resolve a promise.

Besides these, Lwt has a lot of [convenience
functions](https://ocsigen.org/lwt/latest/api/Lwt), and an [asychronous
I/O library](https://ocsigen.org/lwt/latest/api/Lwt_unix).
As you can see, we use `try` to catch both exceptions and rejections.

<!-- TODO Link to read_file and write_file helpers. -->
<!-- TODO Link to Lwt_unix, Lwt_io, Lwt. -->

<br>

To use `let%lwt`, we need to modify our
[`dune`](https://github.com/aantron/dream/blob/master/example/5-promise/dune)
file a bit to include `lwt_ppx`:

<pre><code>(executable
(name promise)
(libraries dream)
<b>(preprocess (pps lwt_ppx)))</b>
</code></pre>

There are other ways to write *await* and *catch* in Lwt that don't require
`lwt_ppx`, but `lwt_ppx` is presently the best for preserving nice stack traces.
For example, `let%lwt` is equivalent to...

- [`Lwt.bind`](https://github.com/ocsigen/lwt/blob/c5f895e35a38df2d06f19fd23bf553129b9e95b3/src/core/lwt.mli#L475),
which is almost never used directly.
- [`>>=`](https://github.com/ocsigen/lwt/blob/c5f895e35a38df2d06f19fd23bf553129b9e95b3/src/core/lwt.mli#L1395)
from module `Lwt.Infix`.
- [`let*`](https://github.com/ocsigen/lwt/blob/c5f895e35a38df2d06f19fd23bf553129b9e95b3/src/core/lwt.mli#L1511)
from module `Lwt.Syntax`, which is showcased in Lwt's
[README](https://github.com/ocsigen/lwt#readme).

We will stick to `let%lwt` in the examples and keep things tidy.

<br>

**Next steps:**

- [**`6-echo`**](../6-echo#files) uses Dream and Lwt to read a request body.
Expand Down
3 changes: 1 addition & 2 deletions example/5-promise/dune
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
(executable
(name promise)
(libraries dream)
(preprocess (pps lwt_ppx)))
(libraries dream))

(data_only_dirs _esy esy.lock lib node_modules)
10 changes: 5 additions & 5 deletions example/5-promise/promise.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ let successful = ref 0
let failed = ref 0

let count_requests inner_handler request =
try%lwt
let%lwt response = inner_handler request in
try
let response = inner_handler request in
successful := !successful + 1;
Lwt.return response

response
with exn ->
failed := !failed + 1;
raise exn

let () =
Dream.run
Eio_main.run @@ fun env ->
Dream.run env
@@ Dream.logger
@@ count_requests
@@ Dream.router [
Expand Down
3 changes: 1 addition & 2 deletions example/6-echo/dune
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
(executable
(name echo)
(libraries dream)
(preprocess (pps lwt_ppx)))
(libraries dream))

(data_only_dirs _esy esy.lock lib node_modules)
5 changes: 3 additions & 2 deletions example/6-echo/echo.ml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
let () =
Dream.run
Eio_main.run @@ fun env ->
Dream.run env
@@ Dream.logger
@@ Dream.router [

Dream.post "/echo" (fun request ->
let%lwt body = Dream.body request in
let body = Dream.body request in
Dream.respond
~headers:["Content-Type", "application/octet-stream"]
body);
Expand Down
3 changes: 1 addition & 2 deletions example/7-template/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ file to run the template preprocessor:

<pre><code>(executable
(name template)
(libraries dream)
(preprocess (pps lwt_ppx)))
(libraries dream))

<b>(rule
(targets template.ml)
Expand Down
3 changes: 2 additions & 1 deletion example/7-template/template.eml.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ let render param =
</html>

let () =
Dream.run
Eio_main.run @@ fun env ->
Dream.run env
@@ Dream.logger
@@ Dream.router [

Expand Down
3 changes: 2 additions & 1 deletion example/8-debug/debug.ml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
let () =
Dream.run ~error_handler:Dream.debug_error_handler
Eio_main.run @@ fun env ->
Dream.run ~error_handler:Dream.debug_error_handler env
@@ Dream.logger
@@ Dream.router [

Expand Down
5 changes: 3 additions & 2 deletions example/9-error/error.eml.ml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ let my_error_template _error debug_info suggested_response =
</body>
</html>
end;
Lwt.return suggested_response
suggested_response

let () =
Dream.run ~error_handler:(Dream.error_template my_error_template)
Eio_main.run @@ fun env ->
Dream.run ~error_handler:(Dream.error_template my_error_template) env
@@ Dream.logger
@@ Dream.not_found
3 changes: 2 additions & 1 deletion example/a-log/log.ml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
let () =
Dream.run
Eio_main.run @@ fun env ->
Dream.run env
@@ Dream.logger
@@ Dream.router [

Expand Down
3 changes: 1 addition & 2 deletions example/b-session/dune
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
(executable
(name session)
(libraries dream)
(preprocess (pps lwt_ppx)))
(libraries dream))

(data_only_dirs _esy esy.lock lib node_modules)
7 changes: 4 additions & 3 deletions example/b-session/session.ml
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
let () =
Dream.run
Eio_main.run @@ fun env ->
Dream.run env
@@ Dream.logger
@@ Dream.memory_sessions
@@ fun request ->

match Dream.session "user" request with
| None ->
let%lwt () = Dream.invalidate_session request in
let%lwt () = Dream.put_session "user" "alice" request in
Dream.invalidate_session request;
Dream.put_session "user" "alice" request;
Dream.html "You weren't logged in; but now you are!"

| Some username ->
Expand Down
5 changes: 3 additions & 2 deletions example/c-cookie/cookie.ml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
let () =
Dream.run
Eio_main.run @@ fun env ->
Dream.run env
@@ Dream.set_secret "foo"
@@ Dream.logger
@@ fun request ->
Expand All @@ -13,4 +14,4 @@ let () =
let response = Dream.response "Set language preference; come again!" in
Dream.add_header response "Content-Type" Dream.text_html;
Dream.set_cookie response "ui.language" "ut-OP" request;
Lwt.return response
response
3 changes: 1 addition & 2 deletions example/d-form/dune
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
(executable
(name form)
(libraries dream)
(preprocess (pps lwt_ppx)))
(libraries dream))

(rule
(targets form.ml)
Expand Down
5 changes: 3 additions & 2 deletions example/d-form/form.eml.ml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ let show_form ?message request =
</html>

let () =
Dream.run
Eio_main.run @@ fun env ->
Dream.run env
@@ Dream.logger
@@ Dream.memory_sessions
@@ Dream.router [
Expand All @@ -27,7 +28,7 @@ let () =

Dream.post "/"
(fun request ->
match%lwt Dream.form request with
match Dream.form request with
| `Ok ["message", message] ->
Dream.html (show_form ~message request)
| _ ->
Expand Down
2 changes: 1 addition & 1 deletion example/e-json/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ To get this working, we have to add `ppx_yojson_conv` to our
<pre><code>(executable
(name json)
(libraries dream)
<b>(preprocess (pps lwt_ppx ppx_yojson_conv)))</b>
<b>(preprocess (pps ppx_yojson_conv)))</b>
</code></pre>

and to
Expand Down
Loading