Skip to content

Commit

Permalink
Detect invalid content_types_provided return values earlier
Browse files Browse the repository at this point in the history
Before this change invalid return values would be detected
via unhelpful error messages such as [1] and the closing
of the connection.

[1] Bad value on output port 'tcp_inet'
  • Loading branch information
essen committed Feb 9, 2025
1 parent fbd680f commit 72b57a8
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 4 deletions.
12 changes: 8 additions & 4 deletions src/cowboy_rest.erl
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ content_types_provided(Req, State) ->
{[], Req2, State2} ->
not_acceptable(Req2, State2);
{CTP, Req2, State2} ->
CTP2 = [normalize_content_types(P) || P <- CTP],
CTP2 = [normalize_content_types(P, provide) || P <- CTP],
State3 = State2#state{content_types_p=CTP2},
try cowboy_req:parse_header(<<"accept">>, Req2) of
undefined ->
Expand All @@ -491,10 +491,14 @@ content_types_provided(Req, State) ->
end
end.

normalize_content_types({ContentType, Callback})
normalize_content_types({ContentType, Callback}, _)
when is_binary(ContentType) ->
{cow_http_hd:parse_content_type(ContentType), Callback};
normalize_content_types(Normalized) ->
normalize_content_types(Normalized = {{Type, SubType, _}, _}, _)
when is_binary(Type), is_binary(SubType) ->
Normalized;
%% Wildcard for content_types_accepted.
normalize_content_types(Normalized = {'*', _}, accept) ->
Normalized.

prioritize_accept(Accept) ->
Expand Down Expand Up @@ -1059,7 +1063,7 @@ accept_resource(Req, State) ->
{Switch, Req2, State2} when element(1, Switch) =:= switch_handler ->
switch_handler(Switch, Req2, State2);
{CTA, Req2, State2} ->
CTA2 = [normalize_content_types(P) || P <- CTA],
CTA2 = [normalize_content_types(P, accept) || P <- CTA],
try cowboy_req:parse_header(<<"content-type">>, Req2) of
%% We do not match against the boundary parameter for multipart.
{Type = <<"multipart">>, SubType, Params} ->
Expand Down
5 changes: 5 additions & 0 deletions test/handlers/content_types_provided_h.erl
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@
init(Req, Opts) ->
{cowboy_rest, Req, Opts}.

content_types_provided(Req=#{qs := <<"invalid-type">>}, State) ->
ct_helper:ignore(cowboy_rest, normalize_content_types, 2),
{[{{'*', '*', '*'}, get_text_plain}], Req, State};
content_types_provided(Req=#{qs := <<"wildcard-param">>}, State) ->
{[{{<<"text">>, <<"plain">>, '*'}, get_text_plain}], Req, State}.

get_text_plain(Req=#{qs := <<"invalid-type">>}, State) ->
{<<"invalid-type">>, Req, State};
get_text_plain(Req=#{qs := <<"wildcard-param">>}, State) ->
{_, _, Param} = maps:get(media_type, Req),
Body = if
Expand Down
12 changes: 12 additions & 0 deletions test/rest_handler_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,18 @@ content_types_accepted_wildcard_param_content_type_with_param(Config) ->
{response, fin, 204, _} = gun:await(ConnPid, Ref),
ok.

content_types_provided_invalid_type(Config) ->
doc("When an invalid type is returned from the "
"content_types_provided callback, the "
"resource is incorrect and a 500 response is expected."),
ConnPid = gun_open(Config),
Ref = gun:get(ConnPid, "/content_types_provided?invalid-type", [
{<<"accept">>, <<"*/*">>},
{<<"accept-encoding">>, <<"gzip">>}
]),
{response, _, 500, _} = do_maybe_h3_error(gun:await(ConnPid, Ref)),
ok.

content_types_provided_wildcard_param_no_accept_param(Config) ->
doc("When a wildcard is returned for parameters from the "
"content_types_provided callback, an accept header "
Expand Down

0 comments on commit 72b57a8

Please sign in to comment.