diff options
Diffstat (limited to 'src/cowboy_rest.erl')
-rw-r--r-- | src/cowboy_rest.erl | 184 |
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 |