Host.Router (Beamlet v0.1.0)

Copy Markdown View Source

Mount your modules at URLs your beamlet serves.

live/2 mounts a LiveView page; get/3, post/3, put/3, patch/3 and delete/3 mount a controller action for that verb. Routes persist across restarts, and every route is public: anyone who can reach your beamlet can request it. Redefining a mounted module with replace: true updates what its routes serve; there is no need to unmount and remount.

Two words to keep apart. A path is what you choose and what every function here takes: "/todos", never carrying a prefix the operator may have configured. A URL is what you give people or external services; url/1 builds it. In a template, ~p"/todos" (imported by use Host.Web) turns a path into the browser path a link needs. A path whose first segment is beamlet is your beamlet's own (/beamlet/login, /beamlet/mcp) and cannot be mounted.

Mounting prints the route and its URL and returns :ok; unmount/1 prints what it removed. print_routes/0 prints the route table. call/4 calls a mounted path in this process and returns the response as data:

call(:get, "/todos")
#=> %{status: 200, headers: %{"content-type" => "text/html; charset=utf-8", ...},
#     body: "<!DOCTYPE html>..."}

Mounting and unmounting act as you, the token behind the eval, and a route records who mounted it. A served route acts as nobody: inside one, these verbs and Host.Code raise, whether the request came from a browser or through call/4, which sets your principal aside for the duration of the request so the two behave the same.

Summary

Types

An HTTP verb a route answers.

Functions

Calls a mounted route and returns its response, e.g. call(:get, "/todos").

Mounts a controller action for DELETE at path; see get/3.

Mounts a controller action for GET at path, e.g. get("/report", Report.Api, :show).

Mounts a LiveView page at path, e.g. live("/todos", Todo.PageLive).

Mounts a controller action for PATCH at path; see get/3.

The browser path for path, e.g. path("/todos").

Mounts a controller action for POST at path, e.g. post("/hooks/github", Hooks.Github, :create).

Prints the mounted routes.

Mounts a controller action for PUT at path; see get/3.

The ~p sigil: the browser path for a route path in a template.

Unmounts every route at path, e.g. unmount("/todos").

The full URL for path, e.g. url("/todos").

Types

verb()

@type verb() :: :get | :post | :put | :patch | :delete

An HTTP verb a route answers.

Functions

call(verb, path, data \\ nil, opts \\ [])

@spec call(verb(), String.t(), map() | String.t() | nil, keyword()) :: %{
  status: pos_integer(),
  headers: %{required(String.t()) => String.t()},
  body: term()
}

Calls a mounted route and returns its response, e.g. call(:get, "/todos").

Or call(:post, "/hooks/github", %{"action" => "opened"}). path is the path you mounted. data is a map or a string: on GET a map becomes the query string; on other verbs a map is sent as a JSON body and a string as the raw body. Pass headers: [{"x-hub-signature", sig}] to add request headers.

Returns %{status: 201, headers: %{"content-type" => ...}, body: ...}. A JSON response body is decoded; any other body is the raw string. A LiveView page answers GET with its rendered HTML. Anything the route prints appears in your output. If the route crashes, the crash is raised here with the route's stacktrace. The call is a real request: records and files the route creates persist, and the route acts as nobody, exactly as it does from a browser.

delete(path, module, action)

@spec delete(String.t(), module(), atom()) :: :ok

Mounts a controller action for DELETE at path; see get/3.

get(path, module, action)

@spec get(String.t(), module(), atom()) :: :ok

Mounts a controller action for GET at path, e.g. get("/report", Report.Api, :show).

The action is called as show(conn, params); the route and its URL are printed. Controller routes answer JSON/webhook-style requests: no session, no CSRF, so external services can call them directly. The module must be a Phoenix controller (use Host.Web, :controller).

live(path, module, action \\ nil)

@spec live(String.t(), module(), atom() | nil) :: :ok

Mounts a LiveView page at path, e.g. live("/todos", Todo.PageLive).

Prints the route and the URL it is served at. The module must be a LiveView (use Host.Web, :live_view). An optional live action arrives as socket.assigns.live_action, not in the mount params, so one LiveView can serve several paths: live("/todos/new", Todo.PageLive, :new).

patch(path, module, action)

@spec patch(String.t(), module(), atom()) :: :ok

Mounts a controller action for PATCH at path; see get/3.

path(path)

@spec path(String.t()) :: String.t()

The browser path for path, e.g. path("/todos").

It is "/todos" on a beamlet serving at the root, and "/app/todos" on one whose operator fenced agent routes under /app. In a template, ~p"/todos" is the same thing; use this form in code.

post(path, module, action)

@spec post(String.t(), module(), atom()) :: :ok

Mounts a controller action for POST at path, e.g. post("/hooks/github", Hooks.Github, :create).

Prints the route and its URL, the one external services should call. See get/3 for what a controller route is.

put(path, module, action)

@spec put(String.t(), module(), atom()) :: :ok

Mounts a controller action for PUT at path; see get/3.

sigil_p(path, modifiers)

(macro)

The ~p sigil: the browser path for a route path in a template.

For links and forms, <.link navigate={~p"/todos/#{id}"}>. It is path/1 in sigil form: it prepends the operator's prefix, if any, and nothing else, so there is no compile-time route check. Comes imported with use Host.Web.

unmount(path, opts \\ [])

@spec unmount(String.t(), keyword()) :: :ok

Unmounts every route at path, e.g. unmount("/todos").

The page or action stops being served, and each route removed is printed. Pass verb: :post to remove only that verb's route and leave the others mounted.

url(path)

@spec url(String.t()) :: String.t()

The full URL for path, e.g. url("/todos").

Something like "http://localhost:4000/todos": what you show people and register with external services.