March Docs

Router

Bastion.Router — declarative, pattern-matched HTTP routing.

Routes are registered with method-specific helpers (get, post, put, patch, delete) and dispatched via Router.to_plug/1, which converts the Router into a plain HttpServer plug (Conn -> Conn).

Path parameter syntax: a segment starting with ":" is a wildcard that matches any single path segment and stores the captured value in conn assigns under the segment name (without the ":").

Handlers can return either Conn directly (plug-style) or Controller.ActionResult (controller-style). For ActionResult handlers, the router applies the fallback on Error automatically.

Use Router.get/post/... for plain Conn -> Conn handlers (plugs), and Router.action for handlers that return Controller.ActionResult. The router's fallback handles ActionResult errors and unmatched routes.

Example:

let router =
  Router.new()
  |> Router.fallback(fn conn -> fn result ->
    match result do
    ActionOk(c) -> c
    ActionError(status, msg) ->
      HttpServer.json(conn, status, "{\"error\":\"" ++ msg ++ "\"}")
    end
  )
  |> Router.action(:get, "/",          fn conn -> PageController.home(conn))
  |> Router.action(:get, "/users/:id", fn conn -> UserController.show(conn))
  |> Router.get("/health",            fn conn -> health_check(conn))

Inside show, retrieve :id with HttpServer.get_assign(conn, "id").

Types

typeRouteRoute = Route(Atom, List(String), Conn -> Conn)#
typeFallbackFallback = Fallback(Conn -> ActionResult -> Conn)#
typeRouterRouter = Router(List(Route), Fallback)#

Functions

fnactionaction(router : Router, method : Atom, pattern : String, handler : Conn -> ActionResult) : Router#

Register a route whose handler returns Controller.ActionResult.

On Ok(conn), the conn is returned as-is.  On Error(status, message),
the router's fallback handler renders the error response.  This is the
recommended way to wire controller actions — the fallback is applied
once at the router level rather than repeated in every handler.

Example:
  Router.action(router, Get, "/users/:id", fn conn -> UserController.show(conn))
fndeletedelete(router : Router, pattern : String, handler : Conn -> Conn) : Router#

Register a DELETE handler for the given path pattern.

fndispatchdispatch(router : Router, conn : Conn) : Conn#

Dispatch an incoming conn to the first matching route.

Extracts path parameters and stores them in conn assigns before calling
the handler. If no route matches, the router's fallback is invoked with
a 404 error — so the fallback acts as the last arm of the match.
fnfallbackfallback(router : Router, handler : Conn -> ActionResult -> Conn) : Router#

Set the fallback handler for this router.

The fallback is called when a controller action returns Controller.Error,
and also when no route matches (as a 404 error).

Example:
  -- For an API router that returns JSON errors:
  Router.new()
  |> Router.fallback(fn conn -> fn result ->
    match result do
    Controller.ActionOk(c) -> c
    Controller.ActionError(status, msg) ->
      HttpServer.json(conn, status, "{\"error\":\"" ++ msg ++ "\"}")
    end
  )
fngetget(router : Router, pattern : String, handler : Conn -> Conn) : Router#

Register a GET handler for the given path pattern.

Segments starting with ":" are captured as path parameters.

Example:
  Router.get(router, "/users/:id", show_user)
fnnewnew() : Router#

Create a new empty router with the default HTML error fallback.

fnpatchpatch(router : Router, pattern : String, handler : Conn -> Conn) : Router#

Register a PATCH handler for the given path pattern.

fnpostpost(router : Router, pattern : String, handler : Conn -> Conn) : Router#

Register a POST handler for the given path pattern.

fnputput(router : Router, pattern : String, handler : Conn -> Conn) : Router#

Register a PUT handler for the given path pattern.

fnscopescope(router : Router, prefix : String, sub_router : Router) : Router#

Mount a sub-router under a path prefix.

All routes in sub_router have the prefix prepended to their patterns.

Example:
  Router.scope(router, "/api", api_sub_router)
fnto_plugto_plug(router : Router) : Conn -> Conn#

Convert a Router into a plug function (Conn -> Conn). Pass the result to HttpServer.plug/2 or Bastion.start/2.