Current section
Files
Jump to
Current section
Files
lib/concerto_plug.ex
defmodule Concerto.Plug do
defmodule NotFoundError do
defexception [:method, :path_info]
def message(%{method: method, path_info: path_info}) do
"#{method} #{Concerto.Plug.Mazurka.__format_path__(path_info)} not found"
end
defimpl Plug.Exception do
def status(_) do
404
end
end
end
defmacro __using__(opts) do
router_key = opts[:router_key] || :concerto_router
route_key = opts[:route_key] || :concert_route
plug_init = Keyword.get(opts, :plug_init, true)
quote do
unquote(if plug_init do
quote do
@before_compile unquote(__MODULE__)
use Plug.Builder
end
end)
@doc false
def match(%{private: %{unquote(route_key) => _}} = conn, _opts) do
conn
|> Plug.Conn.put_private(unquote(router_key), __MODULE__)
end
def match(%Plug.Conn{method: method, path_info: path, private: private} = conn, _opts) do
case match(method, Enum.map(path, &URI.decode/1)) do
{module, params} ->
conn
|> Map.merge(%{
params: params,
private: Map.merge(private, %{
unquote(route_key) => module,
unquote(router_key) => __MODULE__
})
})
nil ->
exception = Concerto.Plug.NotFoundError.exception(method: method, path_info: path)
raise Plug.Conn.WrapperError.exception(conn: conn, kind: :error, reason: exception)
end
end
@doc false
def dispatch(%Plug.Conn{private: %{unquote(route_key) => route}} = conn, _opts) do
route.call(conn, [])
end
end
end
defmacro __before_compile__(_) do
quote do
if !Enum.member?(@plugs, {:match, [], true}) do
require Plug.Builder
Plug.Builder.plug :match
end
if !Enum.member?(@plugs, {:dispatch, [], true}) do
require Plug.Builder
Plug.Builder.plug :dispatch
end
end
end
end