From 329b2fa01ef997e2cf723b5beb25c1feb9e74b16 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Fri, 4 Nov 2011 14:37:36 +0100 Subject: Introduce cowboy_http:word/2 Used to parse either a token or a quoted string in parameters values. --- src/cowboy_http.erl | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'src/cowboy_http.erl') diff --git a/src/cowboy_http.erl b/src/cowboy_http.erl index 6d14961..8f2d934 100644 --- a/src/cowboy_http.erl +++ b/src/cowboy_http.erl @@ -1,4 +1,5 @@ %% Copyright (c) 2011, Loïc Hoguin +%% Copyright (c) 2011, Anthony Ramine %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above @@ -106,19 +107,11 @@ media_range_param_value(Data, Fun, Type, SubType, Acc, <<"q">>) -> fun (Rest, Quality) -> accept_ext(Rest, Fun, Type, SubType, Acc, Quality, []) end); -media_range_param_value(Data = << $", _/bits >>, Fun, - Type, SubType, Acc, Attr) -> - quoted_string(Data, +media_range_param_value(Data, Fun, Type, SubType, Acc, Attr) -> + word(Data, fun (Rest, Value) -> media_range_params(Rest, Fun, Type, SubType, [{Attr, Value}|Acc]) - end); -media_range_param_value(Data, Fun, Type, SubType, Acc, Attr) -> - token(Data, - fun (_Rest, <<>>) -> {error, badarg}; - (Rest, Value) -> - media_range_params(Rest, Fun, - Type, SubType, [{Attr, Value}|Acc]) end). -spec accept_ext(binary(), fun(), binary(), binary(), @@ -154,17 +147,9 @@ accept_ext_attr(Data, Fun, Type, SubType, Params, Quality, Acc) -> -spec accept_ext_value(binary(), fun(), binary(), binary(), [{binary(), binary()}], 0..1000, [{binary(), binary()} | binary()], binary()) -> any(). -accept_ext_value(Data = << $", _/bits >>, Fun, - Type, SubType, Params, Quality, Acc, Attr) -> - quoted_string(Data, - fun (Rest, Value) -> - accept_ext(Rest, Fun, - Type, SubType, Params, Quality, [{Attr, Value}|Acc]) - end); accept_ext_value(Data, Fun, Type, SubType, Params, Quality, Acc, Attr) -> - token(Data, - fun (_Rest, <<>>) -> {error, badarg}; - (Rest, Value) -> + word(Data, + fun (Rest, Value) -> accept_ext(Rest, Fun, Type, SubType, Params, Quality, [{Attr, Value}|Acc]) end). @@ -543,6 +528,16 @@ alpha(<< C, Rest/bits >>, Fun, Acc) alpha(Data, Fun, Acc) -> Fun(Data, Acc). +%% @doc Parse either a token or a quoted string. +-spec word(binary(), fun()) -> any(). +word(Data = << $", _/bits >>, Fun) -> + quoted_string(Data, Fun); +word(Data, Fun) -> + token(Data, + fun (_Rest, <<>>) -> {error, badarg}; + (Rest, Token) -> Fun(Rest, Token) + end). + %% @doc Parse a case-insensitive token. %% %% Changes all characters to lowercase. -- cgit v1.2.3 From b184b3588db5aab17b74269b9b81d640c559da4f Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Fri, 4 Nov 2011 15:07:00 +0100 Subject: Introduce cowboy_http:media_type/2 --- src/cowboy_http.erl | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'src/cowboy_http.erl') diff --git a/src/cowboy_http.erl b/src/cowboy_http.erl index 8f2d934..9aeaafe 100644 --- a/src/cowboy_http.erl +++ b/src/cowboy_http.erl @@ -70,13 +70,9 @@ list(Data, Fun, Acc) -> %% @doc Parse a media range. -spec media_range(binary(), fun()) -> any(). media_range(Data, Fun) -> - token_ci(Data, - fun (_Rest, <<>>) -> {error, badarg}; - (<< $/, Rest/bits >>, Type) -> token_ci(Rest, - fun (_Rest2, <<>>) -> {error, badarg}; - (Rest2, SubType) -> - media_range_params(Rest2, Fun, Type, SubType, []) - end) + media_type(Data, + fun (Rest, Type, SubType) -> + media_range_params(Rest, Fun, Type, SubType, []) end). -spec media_range_params(binary(), fun(), binary(), binary(), @@ -114,6 +110,19 @@ media_range_param_value(Data, Fun, Type, SubType, Acc, Attr) -> Type, SubType, [{Attr, Value}|Acc]) end). +%% @doc Parse a media type. +-spec media_type(binary(), fun()) -> any(). +media_type(Data, Fun) -> + token_ci(Data, + fun (_Rest, <<>>) -> {error, badarg}; + (<< $/, Rest/bits >>, Type) -> + token_ci(Rest, + fun (_Rest2, <<>>) -> {error, badarg}; + (Rest2, SubType) -> Fun(Rest2, Type, SubType) + end); + (_Rest, _Type) -> {error, badarg} + end). + -spec accept_ext(binary(), fun(), binary(), binary(), [{binary(), binary()}], 0..1000, [{binary(), binary()} | binary()]) -> any(). -- cgit v1.2.3 From 6fa7659dbb1712926040a3ee257b3fbf21bfd754 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Fri, 4 Nov 2011 15:55:55 +0100 Subject: Support 'Content-Type' in parse_header/2 --- src/cowboy_http.erl | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) (limited to 'src/cowboy_http.erl') 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 = [ -- cgit v1.2.3