Current section
Files
Jump to
Current section
Files
lib/camarero.ex
defmodule Camarero do
@moduledoc false
# idea by Dave Thomas https://twitter.com/pragdave/status/1077775018942185472
defmodule Handler do
@moduledoc false
use Plug.Router
plug(:match)
Module.register_attribute(__MODULE__, :routes, accumulate: true, persist: true)
@root "/" <> (:camarero |> Application.get_env(:root, "") |> String.trim("/"))
defp response!(conn, module, param) do
{status, response} =
case apply(module, :plato_get, [param]) do
{:ok, value} -> {200, %{key: param, value: value}}
:error -> {404, %{key: param, error: :not_found}}
{:error, {status, cause}} -> {status, cause}
end
send_resp(conn, status, Jason.encode!(response))
end
Enum.each(
:camarero
|> Application.get_env(:carta, [])
|> Enum.sort_by(&(&1 |> apply(:plato_route, []) |> String.length()), &>=/2),
fn module ->
route = Enum.join([@root, module |> apply(:plato_route, []) |> String.trim("/")], "/")
@routes {route, module}
get(route) do
values = apply(unquote(module), :all, [])
send_resp(
conn,
200,
Jason.encode!(%{key: "★", value: values})
)
end
get("#{route}/:param") do
response!(conn, unquote(module), param)
end
end
)
def routes, do: @routes
get("#{@root}/*full_path") do
[param | path] = Enum.reverse(full_path)
path = path |> Enum.reverse() |> Enum.join("/")
with {nil, _} <- {Camarero.Catering.Routes.get(path <> "/" <> param), ""},
{nil, _} <- {Camarero.Catering.Routes.get(path), param} do
send_resp(
conn,
400,
Jason.encode!(%{
error: "Handler was not found",
path: Enum.join([@root | full_path], "/")
})
)
else
{module, param} -> response!(conn, module, param)
end
end
# . . .
match(_) do
send_resp(
conn,
400,
Jason.encode!(%{error: "API root was not met", path: conn.request_path})
)
end
plug(:dispatch)
end
defmodule Endpoint do
@moduledoc false
use Plug.Builder
plug(Plug.Logger)
plug(Plug.Parsers,
parsers: [:json],
pass: ["application/json"],
json_decoder: Jason
)
plug(Camarero.Handler)
end
end