2021-04-05 20:57:34 +03:00
..
2021-04-05 00:08:28 +03:00
2021-04-05 00:08:28 +03:00
2021-04-05 20:57:34 +03:00
2021-04-05 20:57:34 +03:00

9-error


You can easily customize all error responses generated by Dream, whether from your application, or at lower levels in the HTTP stack. This is done by passing the ~error_handler parameter to Dream.run. The easiest way to get an error_handler is to call Dream.error_template:

let my_error_template debug_info suggested_response =
  let status = Dream.status suggested_response in
  let code = Dream.status_to_int status
  and reason = Dream.status_to_string status in

  suggested_response
  |> Dream.with_body begin
    <html>
      <body>
        <h1><%i code %> <%s reason %></h1>
%       begin match debug_info with
%       | None -> ()
%       | Some debug_info ->
          <pre><%s debug_info %></pre>
%       end;
      </body>
    </html>
  end
  |> Lwt.return

let () =
  Dream.run ~error_handler:(Dream.error_template my_error_template)
  @@ Dream.logger
  @@ Dream.not_found
$ dune exec --root . ./error.exe

We kept the template simple for the sake of the example, but this is where you'd put in neat graphics to make a beautiful error page!

This app doesn't show debug information by default. However, try adding ~debug:true to Dream.run, rebuilding the app, and accessing it again.


Dream will call the error template for every single error response it generates:

  1. 4xx and 5xx error responses returned by your application.
  2. Exceptions raised by your application.
  3. Whenever the lower-level HTTP servers want to send a response; for instance, a 400 Bad Request due to malformed headers.

The suggested_response argument contains a skeleton response. It is either the response returned by your application in case (1), an empty 500 Internal Server Error if your application raised an exception (2), or a 500 Internal Server Error or 400 Bad Request suggested by the HTTP servers in response to lower-level failures (3).

The easiest thing to do is to decorate suggested_response with a fancy response body, and maybe add some headers. However, you can do anything here, including build up and return a completely new response.


debug_info is None by default. If you passed ~debug:true to Dream.run, it is Some of a string that contains the debug info that we saw in the previous example, 8-debug.


If you don't customize the error handler, Dream defaults to sending only empty responses, so that your application can be fully localization-friendly — even at the lowest levels. Dream carefully avoids hardcoding any strings, even to the point of intercepting strings generated by its HTTP dependencies.


Next steps:

  • a-log shows how to write messages to Dream's log.
  • b-session finally returns to Web development proper, with session management for associating state with clients.

Up to the tutorial index