dream/router

Route configuration and request matching

The router matches incoming requests to controllers based on HTTP method and path patterns. It supports path parameters, wildcards, middleware chains, and custom context/services types.

Basic Routing

import dream/router.{router}
import dream/http/transaction.{Get, Post}

pub fn create_router() {
  router
  |> router.route(Get, "/", controllers.index, [])
  |> router.route(Get, "/users/:id", controllers.show_user, [])
  |> router.route(Post, "/users", controllers.create_user, [])
}

Path Parameters

Use :name to capture path segments as parameters:

Access parameters in your controller with get_param(request, "id").

Wildcards

Wildcards match one or more path segments:

Middleware

Middleware run before (and optionally after) your controller:

router
|> router.route(
  Get,
  "/admin/users",
  controllers.admin_users,
  [auth_middleware, logging_middleware]
)

Middleware are executed in order: authlogging → controller → loggingauth. Each middleware can modify the request on the way in or the response on the way out.

Route Matching

Routes are matched in the order they’re defined. First match wins. More specific routes should come before general ones:

router
|> router.route(Get, "/users/new", controllers.new_user, [])  // Specific
|> router.route(Get, "/users/:id", controllers.show_user, []) // General

Types

Placeholder for when you haven’t defined services yet

Use this as your services type during initial development. Replace it with your own services type when you add database connections, caches, or other shared dependencies.

pub type EmptyServices {
  EmptyServices
}

Constructors

  • EmptyServices

Middleware function wrapper

Middleware intercept requests before they reach controllers and responses before they’re sent back. They’re generic over context and services types so they can work with any application configuration.

pub type Middleware(context, services) {
  Middleware(
    fn(
      request.Request,
      context,
      services,
      fn(request.Request, context, services) -> response.Response,
    ) -> response.Response,
  )
}

Constructors

A single route definition

Combines an HTTP method, path pattern, controller function, and optional middleware. Routes are matched in the order they’re added to the router.

pub type Route(context, services) {
  Route(
    method: request.Method,
    path: String,
    controller: fn(request.Request, context, services) -> response.Response,
    middleware: List(Middleware(context, services)),
  )
}

Constructors

Router holding your application’s routes

The router maintains a list of routes and provides them to the server for request matching. It’s generic over context and services types so the type system can verify your whole app.

pub type Router(context, services) {
  Router(routes: List(Route(context, services)))
}

Constructors

  • Router(routes: List(Route(context, services)))

Values

pub fn build_controller_chain(
  middleware: List(Middleware(context, services)),
  final_controller: fn(request.Request, context, services) -> response.Response,
) -> fn(request.Request, context, services) -> response.Response

Build a controller chain from middleware and final controller

Composes middleware with the controller to create a single function. Middleware execute in order on the way in, then in reverse order on the way out.

For middleware [auth, logging] with controller handle: Request → auth → logging → handle → logging → auth → Response

pub fn controller(
  route: Route(context, services),
  controller_function: fn(request.Request, context, services) -> response.Response,
) -> Route(context, services)

Set the controller function for the route

pub fn find_route(
  router: Router(context, services),
  request: request.Request,
) -> option.Option(
  #(Route(context, services), List(#(String, String))),
)

Find matching route and extract params

pub fn match_path(
  pattern_string: String,
  path: String,
) -> option.Option(List(#(String, String)))

Match a path against a pattern and extract parameters

Returns the extracted parameters if the path matches the pattern, or None if it doesn’t.

Path Parameters

match_path("/users/:id", "/users/123")
// -> Some([#("id", "123")])

match_path("/users/:user_id/posts/:id", "/users/123/posts/456")
// -> Some([#("user_id", "123"), #("id", "456")])

Wildcards

// Single-segment wildcard
match_path("/assets/*file", "/assets/logo.png")
// -> Some([#("file", "logo.png")])

// Multi-segment wildcard
match_path("/files/**path", "/files/docs/guide.pdf")
// -> Some([#("path", "docs/guide.pdf")])

// Extension matching
match_path("/images/*.jpg", "/images/photo.jpg")
// -> Some([])

// Multiple extensions
match_path("/images/*.{jpg,png}", "/images/photo.jpg")
// -> Some([])
pub fn method(
  route: Route(context, services),
  method_value: request.Method,
) -> Route(context, services)

Set the HTTP method for the route

pub fn middleware(
  route: Route(context, services),
  middleware_list: List(
    fn(
      request.Request,
      context,
      services,
      fn(request.Request, context, services) -> response.Response,
    ) -> response.Response,
  ),
) -> Route(context, services)

Add middleware to the route (accepts a list for convenience)

pub const new: Route(context.AppContext, EmptyServices)

Default route constant with AppContext

pub fn path(
  route: Route(context, services),
  path_value: String,
) -> Route(context, services)

Set the path for the route

pub fn route(
  router: Router(context, services),
  method method_value: request.Method,
  path path_value: String,
  controller controller_function: fn(
    request.Request,
    context,
    services,
  ) -> response.Response,
  middleware middleware_list: List(
    fn(
      request.Request,
      context,
      services,
      fn(request.Request, context, services) -> response.Response,
    ) -> response.Response,
  ),
) -> Router(context, services)

Add a route to the router

Routes are matched in the order they’re added, so put more specific routes first. The path supports parameters (:id), wildcards (*, **), and extensions (*.jpg).

Examples

// Simple route
router.route(router, Get, "/", home_controller, [])

// Route with path parameter
router.route(router, Get, "/users/:id", show_user, [])

// Route with middleware
router.route(router, Post, "/admin/users", create_user, [auth, logging])

// Wildcard route for static files
router.route(router, Get, "/assets/**path", serve_static, [])
pub const router: Router(a, b)

Default router constant with AppContext

Search Document