Browse Source

Improve errors for when the ProvideCallback is missing

Loïc Hoguin 6 years ago
parent
commit
0a5fadc60b
3 changed files with 23 additions and 3 deletions
  1. 4 3
      src/cowboy_rest.erl
  2. 11 0
      test/handlers/provide_callback_missing_h.erl
  3. 8 0
      test/rest_handler_SUITE.erl

+ 4 - 3
src/cowboy_rest.erl

@@ -1069,7 +1069,7 @@ set_resp_body_expires(Req, State) ->
 %% 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{content_type_a={_, Callback}}) ->
+set_resp_body(Req, State=#state{handler=Handler, content_type_a={_, Callback}}) ->
 	try case call(Req, State, Callback) of
 		{stop, Req2, HandlerState2} ->
 			terminate(Req2, State#state{handler_state=HandlerState2});
@@ -1079,8 +1079,9 @@ set_resp_body(Req, State=#state{content_type_a={_, Callback}}) ->
 			State2 = State#state{handler_state=HandlerState2},
 			Req3 = cowboy_req:set_resp_body(Body, Req2),
 			multiple_choices(Req3, State2)
-	end catch Class:Reason = {case_clause, no_call} ->
-		error_terminate(Req, State, Class, Reason)
+	end catch Class:{case_clause, no_call} ->
+		error_terminate(Req, State, Class, {error, {missing_callback, {Handler, Callback, 2}},
+			'A callback specified in content_types_provided/2 is not exported.'})
 	end.
 
 multiple_choices(Req, State) ->

+ 11 - 0
test/handlers/provide_callback_missing_h.erl

@@ -0,0 +1,11 @@
+-module(provide_callback_missing_h).
+
+-export([init/2]).
+-export([content_types_provided/2]).
+
+init(Req, State) ->
+	{cowboy_rest, Req, State}.
+
+content_types_provided(Req, State) ->
+	ct_helper_error_h:ignore(cowboy_rest, set_resp_body, 2),
+	{[{<<"text/plain">>, provide}], Req, State}.

+ 8 - 0
test/rest_handler_SUITE.erl

@@ -38,6 +38,7 @@ end_per_group(Name, _) ->
 
 init_dispatch(_) ->
 	cowboy_router:compile([{'_', [
+		{"/provide_callback_missing", provide_callback_missing_h, []},
 		{"/switch_handler", switch_handler_h, run},
 		{"/switch_handler_opts", switch_handler_h, hibernate}
 	]}]).
@@ -52,6 +53,13 @@ do_decode(Headers, Body) ->
 
 %% Tests.
 
+provide_callback_missing(Config) ->
+	doc("A 500 response must be sent when the ProvideCallback can't be called."),
+	ConnPid = gun_open(Config),
+	Ref = gun:get(ConnPid, "/provide_callback_missing", [{<<"accept-encoding">>, <<"gzip">>}]),
+	{response, fin, 500, _} = gun:await(ConnPid, Ref),
+	ok.
+
 switch_handler(Config) ->
 	doc("Switch REST to loop handler for streaming the response body."),
 	ConnPid = gun_open(Config),