Current section
Files
Jump to
Current section
Files
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
@behaviour Plug
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} ->
host_match = Plug.Router.Utils.build_host_match(host)
{_, path_match} = Plug.Router.Utils.build_path_match(path <> "/*glob")
quote do
def route_plug(%Plug.Conn{host: unquote(host_match), path_info: unquote(path_match)} = conn, opts) do
Plug.Router.Utils.forward(conn, 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