Current section

Files

Jump to
kraft src kraft_rest.erl
Raw

src/kraft_rest.erl

-module(kraft_rest).
-behaviour(kraft_handler).
% Callbacks
-export([exec/1]).
-callback get(kraft_conn:path(), kraft_conn:conn()) -> kraft:response().
-callback post(kraft_conn:path(), kraft_conn:conn()) -> kraft:response().
-callback delete(kraft_conn:path(), kraft_conn:conn()) -> kraft:response().
-optional_callbacks([get/2, post/2, delete/2]).
%--- Callbacks -----------------------------------------------------------------
exec(Conn0) ->
#{handler := Module, route := Route} = kraft_conn:'_meta'(Conn0),
handle(Conn0, Module, Route).
%--- Internal ------------------------------------------------------------------
handle(#{method := Method} = Conn0, Module, Route) ->
Conn1 = kraft_conn:await_body(Conn0),
Prefix = kraft_util:split_path(Route),
try
apply(Module, method(Method), [
prefix(maps:get(path, Conn1), Prefix), Conn1
])
catch
error:undef:StackTrace ->
return_error_code(undef, Module, Method, StackTrace, 405);
error:function_clause:StackTrace ->
return_error_code(function_clause, Module, Method, StackTrace, 404)
end.
return_error_code(Type, Module, Method, StackTrace, Code) ->
case StackTrace of
[{Module, Method, _, _} | _] -> throw(Code);
_ -> erlang:raise(error, Type, StackTrace)
end.
method(<<"GET">>) -> get;
method(<<"POST">>) -> post;
method(<<"DELETE">>) -> delete;
method(_) -> throw(501).
prefix([E | L1], [E | L2]) -> prefix(L1, L2);
prefix(L1, [<<"[...]">>]) -> L1.