Current section

Files

Jump to
kraft src kraft_fallback_h.erl
Raw

src/kraft_fallback_h.erl

-module(kraft_fallback_h).
-behaviour(cowboy_stream).
% Callbacks
-export([init/3]).
-export([data/4]).
-export([info/3]).
-export([terminate/3]).
-export([early_error/5]).
%--- Callbacks -----------------------------------------------------------------
init(StreamID, Req, Opts) ->
{Commands0, Next0} = cowboy_stream:init(StreamID, Req, Opts),
{Commands0, #{next => Next0, req => Req}}.
data(StreamID, IsFin, Data, #{next := Next0} = State0) ->
{Commands0, Next1} = cowboy_stream:data(StreamID, IsFin, Data, Next0),
{Commands0, State0#{next => Next1}}.
info(StreamID, Info, #{next := Next0} = State0) ->
{Commands0, Next1} = cowboy_stream:info(StreamID, Info, Next0),
{insert_fallbacks(Commands0, State0), State0#{next => Next1}}.
terminate(StreamID, Reason, #{next := Next0}) ->
cowboy_stream:terminate(StreamID, Reason, Next0).
early_error(StreamID, Reason, PartialReq, Resp, Opts) ->
cowboy_stream:early_error(StreamID, Reason, PartialReq, Resp, Opts).
%--- Internal ------------------------------------------------------------------
insert_fallbacks(Commands0, State) ->
lists:map(fun(C) -> insert_fallback(C, State) end, Commands0).
insert_fallback({response, 403 = Code, Headers, <<>>}, State) ->
render(Code, State, Headers);
insert_fallback({response, 404 = Code, Headers, <<>>}, State) ->
render(Code, State, Headers);
insert_fallback(Command, _State) ->
Command.
render(Code, #{req := Req}, Headers) ->
Conn0 = kraft_conn:'_set_meta'(kraft_conn:new(Req, #{}), app, kraft),
Conn1 = kraft_template:response(Conn0, "error.html", context(Code, Conn0)),
Body = kraft_conn:response_body(Conn1),
Conn3 = kraft_conn:response_headers(Conn1, Headers#{
<<"content-length">> => integer_to_binary(iolist_size(Body))
}),
FinalHeaders = kraft_conn:response_headers(Conn3),
{response, Code, FinalHeaders, Body}.
context(Code, #{method := Method, path := Path}) ->
#{
title => kraft_http:status(Code),
warning => true,
properties => [
#{name => method, value => Method},
#{name => path, value => Path}
]
}.