2-middleware
Middleware is just functions that take handlers and wrap them, producing
handlers that do a little bit more. This example takes the handler from
1-hello and wraps it in one of the most useful
middlewares, the logger:
let () =
Dream.run
(Dream.logger (fun _ ->
Dream.respond "Good morning, world!"))
However, as you can see, the more middlewares we stack on top of each other
like this, the more parentheses and indentation we will end up with! To keep
the code tidy, we use @@, the
standard OCaml operator for calling functions without parentheses. So, the actual
code in this example looks like this:
let () =
Dream.run
@@ Dream.logger
@@ fun _ ->
Dream.respond "Good morning, world!"
When you run this server and visit http://localhost:8080, you get much more interesting (and colorful!) output:
$ dune exec --root . ./middleware.exe
08.03.21 22:19:21.126 Running on http://localhost:8080
08.03.21 22:19:21.126 Press ENTER to stop
08.03.21 22:19:24.927 dream.log INFO REQ 1 GET / 127.0.0.1:58549 Mozilla/5.0 ...
08.03.21 22:19:24.928 dream.log INFO REQ 1 200 in 217 μs
You can write your own messages to the log using Dream.log. See example
9-logging for more logging options. Now that we have
the logger, we will use it in all other examples, even though it's not really
necessary — it just makes it much easier to see what is going on.
There's not much else to middlewares — they are really just functions
from handlers to handlers, so you can create them anywhere. Example
4-counter already shows a simple custom middleware.
There are also more complicated middlewares defined in
m-locals,w-auto-reload, andw-index-html.
Next steps:
- The next example,
3-router, shows routes, the other way to build up handlers in Dream. 4-counterbuilds the first custom middleware.