Current section
Files
Jump to
Current section
Files
src/kraft_controller.erl
-module(kraft_controller).
-behaviour(cowboy_handler).
% API
-export([init/2]).
%--- Types ---------------------------------------------------------------------
-callback init(kraft:conn(), kraft:params()) ->
{kraft:status(), kraft:headers(), kraft:body()}.
%--- API -----------------------------------------------------------------------
init(#{path := Path, method := Method} = Req, #{handler := Handler} = State) ->
try
Conn = kraft_conn:new(Req, State),
{Status, Headers, Body} =
case Handler:init({Req, State}, kraft_conn:params(Conn)) of
{C, H, {kraft_template, TH, B}} -> {C, maps:merge(TH, H), B};
{C, H, B} when is_binary(B) -> {C, H, B}
end,
Resp = cowboy_req:reply(Status, Headers, Body, Req),
{ok, Resp, State}
catch
Class:Reason:Stacktrace ->
EHeaders = #{<<"content-type">> => <<"text/html">>},
EBody = kraft_template:render(kraft, "500.html", #{
req => #{
url => Path,
method => Method
},
exception => #{
class => Class,
reason => io_lib:format("~p", [Reason]),
stacktrace => format_stacktrace(Stacktrace)
}
}),
EResp = cowboy_req:reply(500, EHeaders, EBody, Req),
{ok, EResp, State}
end.
%--- Internal ------------------------------------------------------------------
format_stacktrace(Stacktrace) ->
lists:map(fun format_stacktrace_entry/1, Stacktrace).
format_stacktrace_entry({M, F, Arity, _Loc}) when is_integer(Arity) ->
#{module => M, function => F, arity => Arity};
format_stacktrace_entry({M, F, Args, _Loc}) ->
#{
module => M,
function => F,
args => [io_lib:format("~p", [A]) || A <- Args]
}.