diff options
Diffstat (limited to 'src/cowboy_handler.erl')
-rw-r--r-- | src/cowboy_handler.erl | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/src/cowboy_handler.erl b/src/cowboy_handler.erl index 4acb876..7ed7db3 100644 --- a/src/cowboy_handler.erl +++ b/src/cowboy_handler.erl @@ -29,7 +29,8 @@ env :: cowboy_middleware:env(), hibernate = false :: boolean(), loop_timeout = infinity :: timeout(), - loop_timeout_ref :: undefined | reference() + loop_timeout_ref :: undefined | reference(), + resp_sent = false :: boolean() }). %% @private @@ -80,7 +81,7 @@ handler_init(Req, State, Handler, HandlerOpts) -> "** Stacktrace: ~p~n~n", [Handler, init, 3, Class, Reason, HandlerOpts, cowboy_req:to_list(Req), erlang:get_stacktrace()]), - {error, 500, Req} + error_terminate(Req, State) end. -spec upgrade_protocol(Req, #state{}, module(), any(), module()) @@ -112,7 +113,7 @@ handler_handle(Req, State, Handler, HandlerState) -> [Handler, handle, 2, Class, Reason, HandlerState, cowboy_req:to_list(Req), erlang:get_stacktrace()]), handler_terminate(Req, Handler, HandlerState, Reason), - {error, 500, Req} + error_terminate(Req, State) end. %% We don't listen for Transport closes because that would force us @@ -147,6 +148,9 @@ handler_loop_timeout(State=#state{loop_timeout=Timeout, when Req::cowboy_req:req(). handler_loop(Req, State=#state{loop_timeout_ref=TRef}, Handler, HandlerState) -> receive + {cowboy_req, resp_sent} -> + handler_loop(Req, State#state{resp_sent=true}, + Handler, HandlerState); {timeout, TRef, ?MODULE} -> terminate_request(Req, State, Handler, HandlerState, {normal, timeout}); @@ -180,7 +184,7 @@ handler_call(Req, State, Handler, HandlerState, Message) -> [Handler, info, 3, Class, Reason, HandlerState, cowboy_req:to_list(Req), erlang:get_stacktrace()]), handler_terminate(Req, Handler, HandlerState, Reason), - {error, 500, Req} + error_terminate(Req, State) end. -spec terminate_request(Req, #state{}, module(), any(), @@ -205,3 +209,12 @@ handler_terminate(Req, Handler, HandlerState, Reason) -> [Handler, terminate, 3, Class, Reason2, HandlerState, cowboy_req:to_list(Req), erlang:get_stacktrace()]) end. + +%% Only send an error reply if there is no resp_sent message. +-spec error_terminate(Req, #state{}) + -> {error, 500, Req} | {halt, Req} when Req::cowboy_req:req(). +error_terminate(Req, #state{resp_sent=true}) -> + %% Close the connection, but do not attempt sending a reply. + {halt, cowboy_req:set([{connection, close}, {resp_state, done}], Req)}; +error_terminate(Req, _) -> + {error, 500, Req}. |