aboutsummaryrefslogtreecommitdiffstats
path: root/src/cowboy_rest.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/cowboy_rest.erl')
-rw-r--r--src/cowboy_rest.erl184
1 files changed, 49 insertions, 135 deletions
diff --git a/src/cowboy_rest.erl b/src/cowboy_rest.erl
index 34bfce1..862ebbf 100644
--- a/src/cowboy_rest.erl
+++ b/src/cowboy_rest.erl
@@ -66,30 +66,26 @@
-> {ok, Req, Env} | {error, 500, Req}
when Req::cowboy_req:req(), Env::cowboy_middleware:env().
upgrade(Req, Env, Handler, HandlerOpts) ->
- try
- Method = cowboy_req:get(method, Req),
- case erlang:function_exported(Handler, rest_init, 2) of
- true ->
- try Handler:rest_init(Req, HandlerOpts) of
- {ok, Req2, HandlerState} ->
- service_available(Req2, #state{env=Env, method=Method,
- handler=Handler, handler_state=HandlerState})
- catch Class:Reason ->
- error_logger:error_msg(
- "** Cowboy handler ~p terminating in ~p/~p~n"
- " for the reason ~p:~p~n** Options were ~p~n"
- "** Request was ~p~n** Stacktrace: ~p~n~n",
- [Handler, rest_init, 2, Class, Reason, HandlerOpts,
- cowboy_req:to_list(Req), erlang:get_stacktrace()]),
- {error, 500, Req}
- end;
- false ->
- service_available(Req, #state{env=Env, method=Method,
- handler=Handler})
- end
- catch
- throw:{?MODULE, error} ->
- {error, 500, Req}
+ Method = cowboy_req:get(method, Req),
+ case erlang:function_exported(Handler, rest_init, 2) of
+ true ->
+ try Handler:rest_init(Req, HandlerOpts) of
+ {ok, Req2, HandlerState} ->
+ service_available(Req2, #state{env=Env, method=Method,
+ handler=Handler, handler_state=HandlerState})
+ catch Class:Reason ->
+ cowboy_req:maybe_reply(500, Req),
+ erlang:Class([
+ {reason, Reason},
+ {mfa, {Handler, rest_init, 2}},
+ {stacktrace, erlang:get_stacktrace()},
+ {req, cowboy_req:to_list(Req)},
+ {opts, HandlerOpts}
+ ])
+ end;
+ false ->
+ service_available(Req, #state{env=Env, method=Method,
+ handler=Handler})
end.
service_available(Req, State) ->
@@ -516,14 +512,7 @@ variances(Req, State=#state{content_types_p=CTP,
resource_exists(Req3, State2)
end
catch Class:Reason ->
- error_logger:error_msg(
- "** Cowboy handler ~p terminating in ~p/~p~n"
- " for the reason ~p:~p~n** Handler state was ~p~n"
- "** Request was ~p~n** Stacktrace: ~p~n~n",
- [State#state.handler, variances, 2,
- Class, Reason, State#state.handler_state,
- cowboy_req:to_list(Req), erlang:get_stacktrace()]),
- error_terminate(Req, State)
+ error_terminate(Req, State, Class, Reason, variances)
end.
variances(Req, State, Variances) ->
@@ -559,14 +548,7 @@ if_match(Req, State, EtagsList) ->
false -> precondition_failed(Req2, State2)
end
catch Class:Reason ->
- error_logger:error_msg(
- "** Cowboy handler ~p terminating in ~p/~p~n"
- " for the reason ~p:~p~n** Handler state was ~p~n"
- "** Request was ~p~n** Stacktrace: ~p~n~n",
- [State#state.handler, generate_etag, 2,
- Class, Reason, State#state.handler_state,
- cowboy_req:to_list(Req), erlang:get_stacktrace()]),
- error_terminate(Req, State)
+ error_terminate(Req, State, Class, Reason, generate_etag)
end.
if_match_must_not_exist(Req, State) ->
@@ -594,14 +576,7 @@ if_unmodified_since(Req, State, IfUnmodifiedSince) ->
false -> if_none_match_exists(Req2, State2)
end
catch Class:Reason ->
- error_logger:error_msg(
- "** Cowboy handler ~p terminating in ~p/~p~n"
- " for the reason ~p:~p~n** Handler state was ~p~n"
- "** Request was ~p~n** Stacktrace: ~p~n~n",
- [State#state.handler, last_modified, 2,
- Class, Reason, State#state.handler_state,
- cowboy_req:to_list(Req), erlang:get_stacktrace()]),
- error_terminate(Req, State)
+ error_terminate(Req, State, Class, Reason, last_modified)
end.
if_none_match_exists(Req, State) ->
@@ -627,14 +602,7 @@ if_none_match(Req, State, EtagsList) ->
end
end
catch Class:Reason ->
- error_logger:error_msg(
- "** Cowboy handler ~p terminating in ~p/~p~n"
- " for the reason ~p:~p~n** Handler state was ~p~n"
- "** Request was ~p~n** Stacktrace: ~p~n~n",
- [State#state.handler, generate_etag, 2,
- Class, Reason, State#state.handler_state,
- cowboy_req:to_list(Req), erlang:get_stacktrace()]),
- error_terminate(Req, State)
+ error_terminate(Req, State, Class, Reason, generate_etag)
end.
precondition_is_head_get(Req, State=#state{method=Method})
@@ -669,14 +637,7 @@ if_modified_since(Req, State, IfModifiedSince) ->
false -> not_modified(Req2, State2)
end
catch Class:Reason ->
- error_logger:error_msg(
- "** Cowboy handler ~p terminating in ~p/~p~n"
- " for the reason ~p:~p~n** Handler state was ~p~n"
- "** Request was ~p~n** Stacktrace: ~p~n~n",
- [State#state.handler, last_modified, 2,
- Class, Reason, State#state.handler_state,
- cowboy_req:to_list(Req), erlang:get_stacktrace()]),
- error_terminate(Req, State)
+ error_terminate(Req, State, Class, Reason, last_modified)
end.
not_modified(Req, State) ->
@@ -687,24 +648,10 @@ not_modified(Req, State) ->
{Req4, State3} ->
respond(Req4, State3, 304)
catch Class:Reason ->
- error_logger:error_msg(
- "** Cowboy handler ~p terminating in ~p/~p~n"
- " for the reason ~p:~p~n** Handler state was ~p~n"
- "** Request was ~p~n** Stacktrace: ~p~n~n",
- [State#state.handler, expires, 2,
- Class, Reason, State#state.handler_state,
- cowboy_req:to_list(Req), erlang:get_stacktrace()]),
- error_terminate(Req2, State)
+ error_terminate(Req, State, Class, Reason, expires)
end
catch Class:Reason ->
- error_logger:error_msg(
- "** Cowboy handler ~p terminating in ~p/~p~n"
- " for the reason ~p:~p~n** Handler state was ~p~n"
- "** Request was ~p~n** Stacktrace: ~p~n~n",
- [State#state.handler, generate_etag, 2,
- Class, Reason, State#state.handler_state,
- cowboy_req:to_list(Req), erlang:get_stacktrace()]),
- error_terminate(Req2, State)
+ error_terminate(Req, State, Class, Reason, generate_etag)
end.
precondition_failed(Req, State) ->
@@ -829,17 +776,8 @@ choose_content_type(Req, State, {Type, SubType, Param},
choose_content_type(Req, State, ContentType, [_Any|Tail]) ->
choose_content_type(Req, State, ContentType, Tail).
-process_content_type(Req, State=#state{method=Method,
- handler=Handler, handler_state=HandlerState,
- exists=Exists}, Fun) ->
- case call(Req, State, Fun) of
- no_call ->
- error_logger:error_msg(
- "** Cowboy handler ~p terminating; "
- "function ~p/~p was not exported~n"
- "** Request was ~p~n** State was ~p~n~n",
- [Handler, Fun, 2, cowboy_req:to_list(Req), HandlerState]),
- {error, 500, Req};
+process_content_type(Req, State=#state{method=Method, exists=Exists}, Fun) ->
+ try case call(Req, State, Fun) of
{halt, Req2, HandlerState2} ->
terminate(Req2, State#state{handler_state=HandlerState2});
{true, Req2, HandlerState2} when Exists ->
@@ -859,6 +797,8 @@ process_content_type(Req, State=#state{method=Method,
Exists -> respond(Req3, State2, 303);
true -> respond(Req3, State2, 201)
end
+ end catch Class:Reason = {case_clause, no_call} ->
+ error_terminate(Req, State, Class, Reason, Fun)
end.
%% If the resource is new and has been created at another location
@@ -881,14 +821,7 @@ set_resp_body_etag(Req, State) ->
{Req2, State2} ->
set_resp_body_last_modified(Req2, State2)
catch Class:Reason ->
- error_logger:error_msg(
- "** Cowboy handler ~p terminating in ~p/~p~n"
- " for the reason ~p:~p~n** Handler state was ~p~n"
- "** Request was ~p~n** Stacktrace: ~p~n~n",
- [State#state.handler, generate_etag, 2,
- Class, Reason, State#state.handler_state,
- cowboy_req:to_list(Req), erlang:get_stacktrace()]),
- error_terminate(Req, State)
+ error_terminate(Req, State, Class, Reason, generate_etag)
end.
%% Set the Last-Modified header if any for the response provided.
@@ -905,14 +838,7 @@ set_resp_body_last_modified(Req, State) ->
set_resp_body_expires(Req3, State2)
end
catch Class:Reason ->
- error_logger:error_msg(
- "** Cowboy handler ~p terminating in ~p/~p~n"
- " for the reason ~p:~p~n** Handler state was ~p~n"
- "** Request was ~p~n** Stacktrace: ~p~n~n",
- [State#state.handler, last_modified, 2,
- Class, Reason, State#state.handler_state,
- cowboy_req:to_list(Req), erlang:get_stacktrace()]),
- error_terminate(Req, State)
+ error_terminate(Req, State, Class, Reason, last_modified)
end.
%% Set the Expires header if any for the response provided.
@@ -921,29 +847,14 @@ set_resp_body_expires(Req, State) ->
{Req2, State2} ->
set_resp_body(Req2, State2)
catch Class:Reason ->
- error_logger:error_msg(
- "** Cowboy handler ~p terminating in ~p/~p~n"
- " for the reason ~p:~p~n** Handler state was ~p~n"
- "** Request was ~p~n** Stacktrace: ~p~n~n",
- [State#state.handler, expires, 2,
- Class, Reason, State#state.handler_state,
- cowboy_req:to_list(Req), erlang:get_stacktrace()]),
- error_terminate(Req, State)
+ error_terminate(Req, State, Class, Reason, expires)
end.
%% Set the response headers and call the callback found using
%% content_types_provided/2 to obtain the request body and add
%% it to the response.
-set_resp_body(Req, State=#state{handler=Handler, handler_state=HandlerState,
- content_type_a={_Type, Callback}}) ->
- case call(Req, State, Callback) of
- no_call ->
- error_logger:error_msg(
- "** Cowboy handler ~p terminating; "
- "function ~p/~p was not exported~n"
- "** Request was ~p~n** State was ~p~n~n",
- [Handler, Callback, 2, cowboy_req:to_list(Req), HandlerState]),
- {error, 500, Req};
+set_resp_body(Req, State=#state{content_type_a={_, Callback}}) ->
+ try case call(Req, State, Callback) of
{halt, Req2, HandlerState2} ->
terminate(Req2, State#state{handler_state=HandlerState2});
{Body, Req2, HandlerState2} ->
@@ -959,6 +870,8 @@ set_resp_body(Req, State=#state{handler=Handler, handler_state=HandlerState,
cowboy_req:set_resp_body(Body, Req2)
end,
multiple_choices(Req3, State2)
+ end catch Class:Reason = {case_clause, no_call} ->
+ error_terminate(Req, State, Class, Reason, Callback)
end.
multiple_choices(Req, State) ->
@@ -1057,13 +970,7 @@ call(Req, State=#state{handler=Handler, handler_state=HandlerState},
try
Handler:Callback(Req, HandlerState)
catch Class:Reason ->
- error_logger:error_msg(
- "** Cowboy handler ~p terminating in ~p/~p~n"
- " for the reason ~p:~p~n** Handler state was ~p~n"
- "** Request was ~p~n** Stacktrace: ~p~n~n",
- [Handler, Callback, 2, Class, Reason, HandlerState,
- cowboy_req:to_list(Req), erlang:get_stacktrace()]),
- error_terminate(Req, State)
+ error_terminate(Req, State, Class, Reason, Callback)
end;
false ->
no_call
@@ -1089,10 +996,17 @@ terminate(Req, State=#state{env=Env}) ->
rest_terminate(Req, State),
{ok, Req, [{result, ok}|Env]}.
--spec error_terminate(cowboy_req:req(), #state{}) -> no_return().
-error_terminate(Req, State) ->
+error_terminate(Req, State=#state{handler=Handler, handler_state=HandlerState},
+ Class, Reason, Callback) ->
rest_terminate(Req, State),
- erlang:raise(throw, {?MODULE, error}, erlang:get_stacktrace()).
+ cowboy_req:maybe_reply(500, Req),
+ erlang:Class([
+ {reason, Reason},
+ {mfa, {Handler, Callback, 2}},
+ {stacktrace, erlang:get_stacktrace()},
+ {req, cowboy_req:to_list(Req)},
+ {state, HandlerState}
+ ]).
rest_terminate(Req, #state{handler=Handler, handler_state=HandlerState}) ->
case erlang:function_exported(Handler, rest_terminate, 2) of