[ANN] ppx_deriving_router — type safe routing for Dream and Melange

Hello OCaml community!

It’s my pleasure to announce a new ppx for deriving Dream routers based on variant type declarations, ppx_deriving_router.

A small example. First we define routes (the signature showcases the generated code):

module Pages : sig
  ...

  val href : t -> string
  (** generate URL from the route *)

  val http_method : t -> [ `DELETE | `GET | `POST | `PUT ]
  (** HTTP method for the route *)

  val handle : (t -> Dream.handler) -> Dream.handler
  (** create a route handler *)
end = struct
  open Ppx_deriving_router_runtime.Primitives

  type t =
    | Home [@GET "/"]
    | About
    | Hello of { name : string; repeat : int option } [@GET "/hello/:name"]
    [@@deriving router]
end

Then we describe how we handle each route:

let handle =
  Pages.handle (fun route _req ->
      match route with
      | Home -> Dream.respond "Home page!"
      | About -> Dream.respond "About page!"
      | Hello { name; repeat } ->
          let name =
            match repeat with
            | Some repeat ->
                List.init repeat (fun _ -> name) |> String.concat ", "
            | None -> name
          in
          Dream.respond (Printf.sprintf "Hello, %s" name))

let () = Dream.run ~interface:"127.0.0.1" ~port:8080 handle

Using generated Pages.href function we can generate URLs for routes:

let () =
  assert (Pages.href Home = "/");
  assert (Pages.href About = "/about");
  assert (Pages.href (Hello { name = "world"; repeat = None }) = "/hello/world");
  assert (Pages.href (Hello { name = "world"; repeat = Some 3 }) = "/hello/world?repeat=3")

The URL matching is done by routes library.

There’s also support for routes that track their response types and the ppx automatically derives JSON encoders and decoders for them (by using melange-json.ppx).

On top of that a separate ppx is provided for Melange which allows to construct type safe HTTP clients (route defintions are shared between server and client).

Happy hacking!

11 Likes