Packages

Route macro for routing to multiple routers in phoenix endpoint (or a plug router)

Current section

Files

Jump to
route lib route.ex
Raw

lib/route.ex

defmodule Route do
@moduledoc """
Route macro for routing to multiple routers in phoenix endpoint (or a plug router)
"""
@doc false
defmacro __using__(_opts) do
quote do
def init(opts), do: opts
def call(conn, opts) do
route_plug(super(conn, opts), [])
end
import Route, only: [route: 1]
Module.register_attribute(__MODULE__, :routes, accumulate: true)
@before_compile Route
end
end
@doc false
defmacro __before_compile__(env) do
Module.get_attribute(env.module, :routes)
|> Enum.reverse()
|> Enum.map(fn {path, host, router} ->
route_path = path <> "/*glob"
host_match = Plug.Router.Utils.build_host_match(host)
{_, path_match} = Plug.Router.Utils.build_path_match(route_path)
quote do
def route_plug(
%Plug.Conn{host: unquote(host_match), path_info: unquote(path_match)} = conn,
opts
) do
conn
|> Plug.Conn.put_private(:plug_route, {unquote(route_path), nil})
|> Plug.Router.Utils.forward(var!(glob), unquote(router), opts)
end
end
end)
end
@doc """
Route requests to a router, accepts several `opts` described below
## Examples
route host: "api.", to: MyAPIRouter
route path: "/admin", to: MyAdminRouter
route to: MyDefaultRouter
## Options
`route/1` accept the following `opts`:
* `:host` - the host which the route should match. Defaults to `nil`
* `:path` - the path which the route should match. Defaults to `""`
* `:to` - a Plug that will be called in case the route matches. Required
"""
defmacro route(opts) do
router = Keyword.fetch!(opts, :to)
path = Keyword.get(opts, :path, "")
host = Keyword.get(opts, :host, nil)
quote do
@routes {unquote(path), unquote(host), unquote(router)}
end
end
end