Packages
nova
0.9.19
0.15.1
0.14.3
0.14.1
0.13.7
0.13.1
0.13.0
0.12.1
0.12.0
0.11.0
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.24
0.9.23
0.9.22
0.9.21
0.9.20
0.9.19
0.9.18
0.9.17
0.9.16
0.9.15
0.9.11
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
0.4.4
0.4.3
0.4.2
0.4.1
0.2.2
0.1.0
0.0.1
0.0.0
Nova is a web application framework
Current section
Files
Jump to
Current section
Files
src/controllers/nova_error_controller.erl
-module(nova_error_controller).
-export([
not_found/1,
server_error/1,
status_code/1
]).
status_code(Req) ->
{status, maps:get(resp_status_code, Req, 200)}.
not_found(Req) ->
%% Check the accept-headers
Accept = cowboy_req:header(<<"accept">>, Req),
AcceptList = binary:split(Accept, <<",">>, [global]),
case {lists:member(<<"application/json">>, AcceptList),
lists:member(<<"text/html">>, AcceptList)} of
{true, _} ->
%% Render a json response
JsonLib = nova:get_env(json_lib, thoas),
Json = erlang:apply(JsonLib, encode, [#{message => "Resource not found"}]),
{status, 404, #{<<"content-type">> => <<"application/json">>}, Json};
{_, true} ->
%% Just assume HTML
Variables = #{status => "Could not find the page you were looking for",
title => "404 Not found",
message => "We could not find the page you were looking for"},
{ok, Body} = nova_error_dtl:render(Variables),
{status, 404, #{<<"content-type">> => <<"text/html">>}, Body};
_ ->
{status, 404, #{<<"content-type">> => <<"text/html">>}, <<>>}
end.
server_error(#{crash_info := #{status_code := StatusCode} = CrashInfo} = Req) ->
Variables = #{status => maps:get(status, CrashInfo, undefined),
title => maps:get(title, CrashInfo, undefined),
message => maps:get(message, CrashInfo, undefined),
extra_msg => maps:get(extra_msg, CrashInfo, undefined),
stacktrace => format_stacktrace(maps:get(stacktrace, CrashInfo, []))},
case application:get_env(nova, render_error_pages, true) of
true ->
case cowboy_req:header(<<"accept">>, Req) of
<<"application/json">> ->
JsonLib = nova:get_env(json_lib, thoas),
Json = erlang:apply(JsonLib, encode, [Variables]),
{status, StatusCode, #{<<"content-type">> => <<"application/json">>}, Json};
<<"text/html">> ->
{ok, Body} = nova_error_dtl:render(Variables),
{status, StatusCode, #{<<"content-type">> => <<"text/html">>}, Body};
_ ->
{status, StatusCode, #{<<"content-type">> => <<"text/html">>}, <<>>}
end;
_ ->
{status, StatusCode}
end;
server_error(#{crash_info := #{class := Class, reason := Reason}} = Req) ->
Stacktrace = maps:get(stacktrace, Req, []),
Variables = #{status => "Internal Server Error",
title => "500 Internal Server Error",
message => "Something internal crashed. Please take a look!",
extra_msg => io_lib:format("Class: ~p<br /> Reason: ~p", [Class, Reason]),
stacktrace => format_stacktrace(Stacktrace)},
case nova:get_environment() of
dev ->
%% We do show a proper error response
case cowboy_req:header(<<"accept">>, Req) of
<<"application/json">> ->
JsonLib = nova:get_env(json_lib, thoas),
Json = erlang:apply(JsonLib, encode, [Variables]),
{status, 500, #{<<"content-type">> => <<"application/json">>}, Json};
<<"text/html">> ->
{ok, Body} = nova_error_dtl:render(Variables),
{status, 500, #{<<"content-type">> => <<"text/html">>}, Body};
_ ->
{status, 500, #{<<"content-type">> => <<"text/html">>}, <<>>}
end;
_ ->
{status, 500}
end.
format_stacktrace(not_enabled) ->
logger:warning("Stacktrace disabled. If you want to enable stacktraces call nova:stracktrace(true) or update your sys.config - Read more in the docs"),
[];
format_stacktrace([]) -> [];
format_stacktrace([{Mod, Func, Arity, [{file, File}, {line, Line}]}|Tl]) ->
Formated = #{module => erlang:atom_to_binary(Mod, utf8),
function => erlang:atom_to_binary(Func, utf8),
arity => format_arity(Arity, []),
file => erlang:list_to_binary(File),
line => Line},
[Formated|format_stacktrace(Tl)];
format_stacktrace([Hd|Tl]) ->
logger:warning("Could not format stacktrace line: ~p", [Hd]),
format_stacktrace(Tl).
format_arity(Arity) when is_pid(Arity) -> list_to_binary(pid_to_list(Arity));
format_arity(Arity) when is_function(Arity) -> <<"fun">>;
format_arity(Arity) -> Arity.
format_arity([], Acc) ->
logger:warning("Acc: ~p~n", [Acc]),
Acc;
format_arity([Head, Tail], Acc) ->
Formated = format_arity(Head),
format_arity(Tail, [Formated | Acc]);
format_arity(Arity, _) when is_function(Arity)->
<<"fun">>;
format_arity(Arity, _) ->
Arity.