defmodule Francis.Plug.Router do
@moduledoc """
Module that imports required macros from Francis and Plug.Router
"""
alias Plug.Conn.WrapperError
alias Plug.Router.Utils
defmacro __using__(opts) do
quote location: :keep do
import Francis
require Logger
@plug_router_to %{}
@before_compile Plug.Router
use Plug.Builder, unquote(opts)
import Plug.Router, except: [get: 2, post: 2, put: 2, delete: 2, patch: 2]
@doc false
def match(conn, _opts) do
do_match(conn, conn.method, Utils.decode_path_info!(conn), conn.host)
rescue
err ->
Logger.error("Failed to match route: #{conn.method} #{conn.request_path}")
conn |> send_resp(404, "Not Found") |> halt()
end
@doc false
def dispatch(%Plug.Conn{} = conn, opts) do
{path, fun} = Map.fetch!(conn.private, :plug_route)
try do
:telemetry.span(
[:plug, :router_dispatch],
%{conn: conn, route: path, router: __MODULE__},
fn ->
conn = fun.(conn, opts)
{conn, %{conn: conn, route: path, router: __MODULE__}}
end
)
catch
kind, reason -> WrapperError.reraise(conn, kind, reason, __STACKTRACE__)
end
end
end
end
end