Current section
Files
Jump to
Current section
Files
lib/maru_swagger.ex
defmodule MaruSwagger do
use Maru.Middleware
def init(opts) do
module_func = fn ->
case Maru.Config.servers do
[{module, _} | _] -> module
_ -> raise "missing configured module for Maru in config.exs (MaruSwagger depends on it!)"
end
end
path = opts |> Keyword.fetch!(:at) |> Maru.Router.Path.split
module = opts |> Keyword.get_lazy(:for, module_func)
prefix_func = fn ->
if Code.ensure_loaded?(Phoenix) do
phoenix_module = Module.concat(Mix.Phoenix.base(), "Router")
phoenix_module.__routes__ |> Enum.filter(fn r ->
match?(%{kind: :forward, plug: ^module}, r)
end)
|> case do
[%{path: p}] -> p |> String.split("/", trim: true)
_ -> []
end
else [] end
end
version = opts |> Keyword.get(:version, nil)
pretty = opts |> Keyword.get(:pretty, false)
prefix = opts |> Keyword.get_lazy(:prefix, prefix_func)
{path, module, version, pretty, prefix}
end
def call(%Plug.Conn{path_info: path_info}=conn, {path, module, version, pretty, prefix}) do
case Maru.Router.Path.lstrip(path_info, path) do
{:ok, []} ->
resp =
generate(module, version, prefix)
|> Poison.encode!(pretty: pretty)
conn
|> Plug.Conn.put_resp_header("access-control-allow-origin", "*")
|> Plug.Conn.send_resp(200, resp)
|> Plug.Conn.halt
_ -> conn
end
end
def generate(module, version, prefix) do
module
|> Maru.Builder.Routers.generate
|> Dict.fetch!(version)
|> Enum.sort(&(&1.path > &2.path))
|> Enum.map(&extract_endpoint(&1, prefix))
|> MaruSwagger.ResponseFormatter.format(module, version)
end
defp extract_endpoint(ep, prefix) do
params = ep |> MaruSwagger.ParamsExtractor.extract_params
method = case ep.method do
{:_, [], nil} -> "MATCH"
m -> m
end
%{
desc: ep.desc,
method: method,
path: prefix ++ ep.path,
params: params,
version: ep.version
}
end
end