0
Fork 0
mirror of https://github.com/ninenines/cowboy.git synced 2025-07-16 05:00:24 +00:00

Fix parsing of the Cookie header

This should be equivalent to what we do in Set-Cookie. Real-world
testing is needed to confirm it works as intended.
This commit is contained in:
Loïc Hoguin 2012-12-20 14:19:39 +01:00
parent f48902cee7
commit 8858ca240f

View file

@ -121,7 +121,7 @@ cookie_list(Data, Acc) ->
fun (<<>>) -> Acc;
(<< $,, Rest/binary >>) -> cookie_list(Rest, Acc);
(<< $;, Rest/binary >>) -> cookie_list(Rest, Acc);
(Rest) -> param(Rest,
(Rest) -> cookie(Rest,
fun (Rest2, << $$, _/bits >>, _) ->
cookie_list(Rest2, Acc);
(Rest2, Name, Value) ->
@ -129,6 +129,50 @@ cookie_list(Data, Acc) ->
end)
end).
-spec cookie(binary(), fun()) -> any().
cookie(Data, Fun) ->
whitespace(Data,
fun (Rest) ->
cookie_name(Rest,
fun (_Rest2, <<>>) -> {error, badarg};
(<< $=, Rest2/binary >>, Name) ->
cookie_value(Rest2,
fun (Rest3, Value) ->
Fun(Rest3, Name, Value)
end);
(_Rest2, _Attr) -> {error, badarg}
end)
end).
-spec cookie_name(binary(), fun()) -> any().
cookie_name(Data, Fun) ->
cookie_name(Data, Fun, <<>>).
-spec cookie_name(binary(), fun(), binary()) -> any().
cookie_name(<<>>, Fun, Acc) ->
Fun(<<>>, Acc);
cookie_name(Data = << C, _Rest/binary >>, Fun, Acc)
when C =:= $=; C =:= $,; C =:= $;; C =:= $\s; C =:= $\t;
C =:= $\r; C =:= $\n; C =:= $\013; C =:= $\014 ->
Fun(Data, Acc);
cookie_name(<< C, Rest/binary >>, Fun, Acc) ->
C2 = cowboy_bstr:char_to_lower(C),
cookie_name(Rest, Fun, << Acc/binary, C2 >>).
-spec cookie_value(binary(), fun()) -> any().
cookie_value(Data, Fun) ->
cookie_value(Data, Fun, <<>>).
-spec cookie_value(binary(), fun(), binary()) -> any().
cookie_value(<<>>, Fun, Acc) ->
Fun(<<>>, Acc);
cookie_value(Data = << C, _Rest/binary >>, Fun, Acc)
when C =:= $,; C =:= $;; C =:= $\s; C =:= $\t;
C =:= $\r; C =:= $\n; C =:= $\013; C =:= $\014 ->
Fun(Data, Acc);
cookie_value(<< C, Rest/binary >>, Fun, Acc) ->
cookie_value(Rest, Fun, << Acc/binary, C >>).
%% @doc Parse a content type.
-spec content_type(binary()) -> any().
content_type(Data) ->
@ -1016,24 +1060,24 @@ cookie_list_test_() ->
{<<"name">>, <<"value">>},
{<<"name2">>, <<"value2">>}
]},
{<<"$Version=\"1\"; Customer=\"WILE_E_COYOTE\"; $Path=\"/acme\"">>, [
{<<"$Version=1; Customer=WILE_E_COYOTE; $Path=/acme">>, [
{<<"customer">>, <<"WILE_E_COYOTE">>}
]},
{<<"$Version=\"1\"; Customer=\"WILE_E_COYOTE\"; $Path=\"/acme\"; "
"Part_Number=\"Rocket_Launcher_0001\"; $Path=\"/acme\"; "
"Shipping=\"FedEx\"; $Path=\"/acme\"">>, [
{<<"$Version=1; Customer=WILE_E_COYOTE; $Path=/acme; "
"Part_Number=Rocket_Launcher_0001; $Path=/acme; "
"Shipping=FedEx; $Path=/acme">>, [
{<<"customer">>, <<"WILE_E_COYOTE">>},
{<<"part_number">>, <<"Rocket_Launcher_0001">>},
{<<"shipping">>, <<"FedEx">>}
]},
%% Potential edge cases (initially from Mochiweb).
{<<"foo=\"\\x\"">>, [{<<"foo">>, <<"x">>}]},
{<<"foo=\\x">>, [{<<"foo">>, <<"\\x">>}]},
{<<"=">>, {error, badarg}},
{<<" foo ; bar ">>, {error, badarg}},
{<<"foo=;bar=">>, {error, badarg}},
{<<"foo=\"\\\";\";bar ">>, {error, badarg}},
{<<"foo=\"\\\";\";bar=good ">>,
[{<<"foo">>, <<"\";">>}, {<<"bar">>, <<"good">>}]},
{<<"foo=;bar=">>, [{<<"foo">>, <<>>}, {<<"bar">>, <<>>}]},
{<<"foo=\\\";;bar ">>, {error, badarg}},
{<<"foo=\\\";;bar=good ">>,
[{<<"foo">>, <<"\\\"">>}, {<<"bar">>, <<"good">>}]},
{<<"foo=\"\\\";bar">>, {error, badarg}},
{<<"">>, {error, badarg}},
{<<"foo=bar , baz=wibble ">>,