The dashboard, its API, and the tracker as a Plug: the SDK's
rl.routes(), the same answers byte for byte, so the dashboard, the MCP
server, and every port's tools work against an Elixir app as they do
against a Node one.
In Phoenix, forward to it outside the :browser pipeline (the routes have
their own cross-site checks, and Phoenix's CSRF plug would refuse the
tracker's posts):
# lib/my_app_web/router.ex
scope "/" do
forward "/runlight", Runlight.Plug
endand in a Plug.Router the same way. The base path is where the router
mounted it. Options are Runlight.Routes's, plus :instance, the
instance's name (default Runlight). Phoenix calls init/1 when the
router compiles, so nothing is read there: the token and the instance are
read on the first request.
A request on a link domain added in Settings, such as go.example.com, is answered with its redirect or a 404 before anything else, as every one of these Plugs does; on every other host the request carries on.
The connection's own address is passed on for the visitor's daily hash
when no trusted proxy header names the client (see the instance's
:trust_proxy).
A Phoenix endpoint's Plug.Parsers reads form and JSON bodies before the
router forwards here. Those reach the routes as the client sent them, a
form as a form and JSON as JSON, rebuilt from what the parsers made of
them. To hand on the exact bytes instead, give the parsers this module's
reader:
plug Plug.Parsers,
parsers: [:urlencoded, :multipart, :json],
json_decoder: Phoenix.json_library(),
body_reader: {Runlight.Plug, :body_reader, []}
Summary
Functions
A body_reader for Plug.Parsers that keeps the bytes it reads, so a
body the parsers have already read reaches the routes byte for byte.
Functions
@spec body_reader(Plug.Conn.t(), keyword()) :: {:ok, binary(), Plug.Conn.t()} | {:more, binary(), Plug.Conn.t()} | {:error, term()}
A body_reader for Plug.Parsers that keeps the bytes it reads, so a
body the parsers have already read reaches the routes byte for byte.