diff options
-rw-r--r-- | src/cowboy_http.erl | 54 | ||||
-rw-r--r-- | src/cowboy_http_req.erl | 5 |
2 files changed, 58 insertions, 1 deletions
diff --git a/src/cowboy_http.erl b/src/cowboy_http.erl index 9aeaafe..6454521 100644 --- a/src/cowboy_http.erl +++ b/src/cowboy_http.erl @@ -17,7 +17,7 @@ -module(cowboy_http). %% Parsing. --export([list/2, nonempty_list/2, +-export([list/2, nonempty_list/2, content_type/1, media_range/2, conneg/2, language_range/2, entity_tag_match/1, http_date/1, rfc1123_date/1, rfc850_date/1, asctime_date/1, digits/1, token/2, token_ci/2, quoted_string/2]). @@ -67,6 +67,41 @@ list(Data, Fun, Acc) -> end) end). +%% @doc Parse a content type. +-spec content_type(binary()) -> any(). +content_type(Data) -> + media_type(Data, + fun (Rest, Type, SubType) -> + content_type_params(Rest, + fun (Params) -> {Type, SubType, Params} end, []) + end). + +-spec content_type_params(binary(), fun(), list({binary(), binary()})) + -> any(). +content_type_params(Data, Fun, Acc) -> + whitespace(Data, + fun (<< $;, Rest/bits >>) -> content_type_param(Rest, Fun, Acc); + (<<>>) -> Fun(lists:reverse(Acc)); + (_Rest) -> {error, badarg} + end). + +-spec content_type_param(binary(), fun(), list({binary(), binary()})) + -> any(). +content_type_param(Data, Fun, Acc) -> + whitespace(Data, + fun (Rest) -> + token_ci(Rest, + fun (_Rest2, <<>>) -> {error, badarg}; + (<< $=, Rest2/bits >>, Attr) -> + word(Rest2, + fun (Rest3, Value) -> + content_type_params(Rest3, Fun, + [{Attr, Value}|Acc]) + end); + (_Rest2, _Attr) -> {error, badarg} + end) + end). + %% @doc Parse a media range. -spec media_range(binary(), fun()) -> any(). media_range(Data, Fun) -> @@ -773,6 +808,23 @@ connection_to_atom_test_() -> [{lists:flatten(io_lib:format("~p", [T])), fun() -> R = connection_to_atom(T) end} || {T, R} <- Tests]. +content_type_test_() -> + %% {ContentType, Result} + Tests = [ + {<<"text/plain; charset=iso-8859-4">>, + {<<"text">>, <<"plain">>, [{<<"charset">>, <<"iso-8859-4">>}]}}, + {<<"multipart/form-data \t;Boundary=\"MultipartIsUgly\"">>, + {<<"multipart">>, <<"form-data">>, [ + {<<"boundary">>, <<"MultipartIsUgly">>} + ]}}, + {<<"foo/bar; one=FirstParam; two=SecondParam">>, + {<<"foo">>, <<"bar">>, [ + {<<"one">>, <<"FirstParam">>}, + {<<"two">>, <<"SecondParam">>} + ]}} + ], + [{V, fun () -> R = content_type(V) end} || {V, R} <- Tests]. + digits_test_() -> %% {Digits, Result} Tests = [ diff --git a/src/cowboy_http_req.erl b/src/cowboy_http_req.erl index 12d117f..fa4e620 100644 --- a/src/cowboy_http_req.erl +++ b/src/cowboy_http_req.erl @@ -244,6 +244,11 @@ parse_header(Name, Req, Default) when Name =:= 'Content-Length' -> fun (Value) -> cowboy_http:digits(Value) end); +parse_header(Name, Req, Default) when Name =:= 'Content-Type' -> + parse_header(Name, Req, Default, + fun (Value) -> + cowboy_http:content_type(Value) + end); parse_header(Name, Req, Default) when Name =:= 'If-Match'; Name =:= 'If-None-Match' -> parse_header(Name, Req, Default, |