diff options
author | Loïc Hoguin <[email protected]> | 2025-02-09 23:34:55 +0100 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2025-02-09 23:40:08 +0100 |
commit | 72b57a846dbacf7ea886b303c680c683a2acec5d (patch) | |
tree | 7daa4286cc4218aecb47a65374b17155572b3805 | |
parent | fbd680f0f6fb5fe99c4345b838cb42aa1afb3283 (diff) | |
download | cowboy-72b57a846dbacf7ea886b303c680c683a2acec5d.tar.gz cowboy-72b57a846dbacf7ea886b303c680c683a2acec5d.tar.bz2 cowboy-72b57a846dbacf7ea886b303c680c683a2acec5d.zip |
Detect invalid content_types_provided return values earlier
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'
-rw-r--r-- | src/cowboy_rest.erl | 12 | ||||
-rw-r--r-- | test/handlers/content_types_provided_h.erl | 5 | ||||
-rw-r--r-- | test/rest_handler_SUITE.erl | 12 |
3 files changed, 25 insertions, 4 deletions
diff --git a/src/cowboy_rest.erl b/src/cowboy_rest.erl index fcea71c..e254c1b 100644 --- a/src/cowboy_rest.erl +++ b/src/cowboy_rest.erl @@ -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 -> @@ -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) -> @@ -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} -> diff --git a/test/handlers/content_types_provided_h.erl b/test/handlers/content_types_provided_h.erl index 5220c19..397026b 100644 --- a/test/handlers/content_types_provided_h.erl +++ b/test/handlers/content_types_provided_h.erl @@ -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 diff --git a/test/rest_handler_SUITE.erl b/test/rest_handler_SUITE.erl index 6c1f1c1..324a50c 100644 --- a/test/rest_handler_SUITE.erl +++ b/test/rest_handler_SUITE.erl @@ -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 " |