aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--rebar.config2
-rw-r--r--src/cowboy_clock.erl20
-rw-r--r--src/cowboy_http.erl211
-rw-r--r--src/cowboy_req.erl14
5 files changed, 6 insertions, 243 deletions
diff --git a/Makefile b/Makefile
index e9c2c53..8a5d521 100644
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@ PLT_APPS = crypto public_key ssl
# Dependencies.
DEPS = cowlib ranch
-dep_cowlib = pkg://cowlib 0.1.0
+dep_cowlib = pkg://cowlib 0.2.0
dep_ranch = pkg://ranch 0.8.5
TEST_DEPS = ct_helper gun
diff --git a/rebar.config b/rebar.config
index d31efe7..91179db 100644
--- a/rebar.config
+++ b/rebar.config
@@ -1,4 +1,4 @@
{deps, [
- {cowlib, ".*", {git, "git://github.com/extend/cowlib.git", "0.1.0"}},
+ {cowlib, ".*", {git, "git://github.com/extend/cowlib.git", "0.2.0"}},
{ranch, ".*", {git, "git://github.com/extend/ranch.git", "0.8.5"}}
]}.
diff --git a/src/cowboy_clock.erl b/src/cowboy_clock.erl
index f21616c..6fb522b 100644
--- a/src/cowboy_clock.erl
+++ b/src/cowboy_clock.erl
@@ -26,7 +26,6 @@
-export([stop/0]).
-export([rfc1123/0]).
-export([rfc1123/1]).
--export([rfc2109/1]).
%% gen_server.
-export([init/1]).
@@ -67,18 +66,6 @@ rfc1123() ->
rfc1123(DateTime) ->
update_rfc1123(<<>>, undefined, DateTime).
-%% @doc Return the given date and time formatted according to RFC-2109.
-%%
-%% This format is used in the <em>set-cookie</em> header sent with
-%% HTTP responses.
--spec rfc2109(calendar:datetime()) -> binary().
-rfc2109({Date = {Y, Mo, D}, {H, Mi, S}}) ->
- Wday = calendar:day_of_the_week(Date),
- << (weekday(Wday))/binary, ", ", (pad_int(D))/binary, "-",
- (month(Mo))/binary, "-", (list_to_binary(integer_to_list(Y)))/binary,
- " ", (pad_int(H))/binary, $:, (pad_int(Mi))/binary,
- $:, (pad_int(S))/binary, " GMT" >>.
-
%% gen_server.
%% @private
@@ -188,13 +175,6 @@ month(12) -> <<"Dec">>.
-ifdef(TEST).
-rfc2109_test_() ->
- Tests = [
- {<<"Sat, 14-May-2011 14:25:33 GMT">>, {{2011, 5, 14}, {14, 25, 33}}},
- {<<"Sun, 01-Jan-2012 00:00:00 GMT">>, {{2012, 1, 1}, { 0, 0, 0}}}
- ],
- [{R, fun() -> R = rfc2109(D) end} || {R, D} <- Tests].
-
update_rfc1123_test_() ->
Tests = [
{<<"Sat, 14 May 2011 14:25:33 GMT">>, undefined,
diff --git a/src/cowboy_http.erl b/src/cowboy_http.erl
index f2defdc..9f06522 100644
--- a/src/cowboy_http.erl
+++ b/src/cowboy_http.erl
@@ -19,7 +19,6 @@
%% Parsing.
-export([list/2]).
-export([nonempty_list/2]).
--export([cookie_list/1]).
-export([content_type/1]).
-export([media_range/2]).
-export([conneg/2]).
@@ -46,7 +45,6 @@
-export([ce_identity/1]).
%% Interpretation.
--export([cookie_to_iodata/3]).
-export([urldecode/1]).
-export([urldecode/2]).
-export([urlencode/1]).
@@ -92,76 +90,6 @@ list(Data, Fun, Acc) ->
end)
end).
-%% @doc Parse a list of cookies.
-%%
-%% We need a special function for this because we need to support both
-%% $; and $, as separators as per RFC2109.
--spec cookie_list(binary()) -> [{binary(), binary()}] | {error, badarg}.
-cookie_list(Data) ->
- case cookie_list(Data, []) of
- {error, badarg} -> {error, badarg};
- [] -> {error, badarg};
- L -> lists:reverse(L)
- end.
-
--spec cookie_list(binary(), Acc) -> Acc | {error, badarg}
- when Acc::[{binary(), binary()}].
-cookie_list(Data, Acc) ->
- whitespace(Data,
- fun (<<>>) -> Acc;
- (<< $,, Rest/binary >>) -> cookie_list(Rest, Acc);
- (<< $;, Rest/binary >>) -> cookie_list(Rest, Acc);
- (Rest) -> cookie(Rest,
- fun (Rest2, << $$, _/binary >>, _) ->
- cookie_list(Rest2, Acc);
- (Rest2, Name, Value) ->
- cookie_list(Rest2, [{Name, Value}|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) ->
- cookie_name(Rest, Fun, << Acc/binary, C >>).
-
--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.
%%
%% We lowercase the charset header as we know it's case insensitive.
@@ -1025,55 +953,6 @@ ce_identity(Data) ->
%% Interpretation.
-%% @doc Convert a cookie name, value and options to its iodata form.
-%% @end
-%%
-%% Initially from Mochiweb:
-%% * Copyright 2007 Mochi Media, Inc.
-%% Initial binary implementation:
-%% * Copyright 2011 Thomas Burdick <[email protected]>
--spec cookie_to_iodata(iodata(), iodata(), cowboy_req:cookie_opts())
- -> iodata().
-cookie_to_iodata(Name, Value, Opts) ->
- case binary:match(iolist_to_binary(Name), [<<$=>>, <<$,>>, <<$;>>,
- <<$\s>>, <<$\t>>, <<$\r>>, <<$\n>>, <<$\013>>, <<$\014>>]) of
- nomatch -> ok
- end,
- case binary:match(iolist_to_binary(Value), [<<$,>>, <<$;>>,
- <<$\s>>, <<$\t>>, <<$\r>>, <<$\n>>, <<$\013>>, <<$\014>>]) of
- nomatch -> ok
- end,
- MaxAgeBin = case lists:keyfind(max_age, 1, Opts) of
- false -> <<>>;
- {_, 0} ->
- %% MSIE requires an Expires date in the past to delete a cookie.
- <<"; Expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0">>;
- {_, MaxAge} when is_integer(MaxAge), MaxAge > 0 ->
- UTC = calendar:universal_time(),
- Secs = calendar:datetime_to_gregorian_seconds(UTC),
- Expires = calendar:gregorian_seconds_to_datetime(Secs + MaxAge),
- [<<"; Expires=">>, cowboy_clock:rfc2109(Expires),
- <<"; Max-Age=">>, integer_to_list(MaxAge)]
- end,
- DomainBin = case lists:keyfind(domain, 1, Opts) of
- false -> <<>>;
- {_, Domain} -> [<<"; Domain=">>, Domain]
- end,
- PathBin = case lists:keyfind(path, 1, Opts) of
- false -> <<>>;
- {_, Path} -> [<<"; Path=">>, Path]
- end,
- SecureBin = case lists:keyfind(secure, 1, Opts) of
- false -> <<>>;
- {_, true} -> <<"; Secure">>
- end,
- HttpOnlyBin = case lists:keyfind(http_only, 1, Opts) of
- false -> <<>>;
- {_, true} -> <<"; HttpOnly">>
- end,
- [Name, <<"=">>, Value, <<"; Version=1">>,
- MaxAgeBin, DomainBin, PathBin, SecureBin, HttpOnlyBin].
-
%% @doc Decode a URL encoded binary.
%% @equiv urldecode(Bin, crash)
-spec urldecode(binary()) -> binary().
@@ -1224,38 +1103,6 @@ nonempty_token_list_test_() ->
],
[{V, fun() -> R = nonempty_list(V, fun token/2) end} || {V, R} <- Tests].
-cookie_list_test_() ->
- %% {Value, Result}.
- Tests = [
- {<<"name=value; name2=value2">>, [
- {<<"name">>, <<"value">>},
- {<<"name2">>, <<"value2">>}
- ]},
- {<<"$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">>, [
- {<<"Customer">>, <<"WILE_E_COYOTE">>},
- {<<"Part_Number">>, <<"Rocket_Launcher_0001">>},
- {<<"Shipping">>, <<"FedEx">>}
- ]},
- %% Potential edge cases (initially from Mochiweb).
- {<<"foo=\\x">>, [{<<"foo">>, <<"\\x">>}]},
- {<<"=">>, {error, badarg}},
- {<<" foo ; bar ">>, {error, badarg}},
- {<<"foo=;bar=">>, [{<<"foo">>, <<>>}, {<<"bar">>, <<>>}]},
- {<<"foo=\\\";;bar ">>, {error, badarg}},
- {<<"foo=\\\";;bar=good ">>,
- [{<<"foo">>, <<"\\\"">>}, {<<"bar">>, <<"good">>}]},
- {<<"foo=\"\\\";bar">>, {error, badarg}},
- {<<"">>, {error, badarg}},
- {<<"foo=bar , baz=wibble ">>,
- [{<<"foo">>, <<"bar">>}, {<<"baz">>, <<"wibble">>}]}
- ],
- [{V, fun() -> R = cookie_list(V) end} || {V, R} <- Tests].
-
media_range_list_test_() ->
%% {Tokens, Result}
Tests = [
@@ -1380,64 +1227,6 @@ digits_test_() ->
],
[{V, fun() -> R = digits(V) end} || {V, R} <- Tests].
-cookie_to_iodata_test_() ->
- %% {Name, Value, Opts, Result}
- Tests = [
- {<<"Customer">>, <<"WILE_E_COYOTE">>,
- [{http_only, true}, {domain, <<"acme.com">>}],
- <<"Customer=WILE_E_COYOTE; Version=1; "
- "Domain=acme.com; HttpOnly">>},
- {<<"Customer">>, <<"WILE_E_COYOTE">>,
- [{path, <<"/acme">>}],
- <<"Customer=WILE_E_COYOTE; Version=1; Path=/acme">>},
- {<<"Customer">>, <<"WILE_E_COYOTE">>,
- [{path, <<"/acme">>}, {badoption, <<"negatory">>}],
- <<"Customer=WILE_E_COYOTE; Version=1; Path=/acme">>}
- ],
- [{R, fun() -> R = iolist_to_binary(cookie_to_iodata(N, V, O)) end}
- || {N, V, O, R} <- Tests].
-
-cookie_to_iodata_max_age_test() ->
- F = fun(N, V, O) ->
- binary:split(iolist_to_binary(
- cookie_to_iodata(N, V, O)), <<";">>, [global])
- end,
- [<<"Customer=WILE_E_COYOTE">>,
- <<" Version=1">>,
- <<" Expires=", _/binary>>,
- <<" Max-Age=111">>,
- <<" Secure">>] = F(<<"Customer">>, <<"WILE_E_COYOTE">>,
- [{max_age, 111}, {secure, true}]),
- case catch F(<<"Customer">>, <<"WILE_E_COYOTE">>, [{max_age, -111}]) of
- {'EXIT', {{case_clause, {max_age, -111}}, _}} -> ok
- end,
- [<<"Customer=WILE_E_COYOTE">>,
- <<" Version=1">>,
- <<" Expires=", _/binary>>,
- <<" Max-Age=86417">>] = F(<<"Customer">>, <<"WILE_E_COYOTE">>,
- [{max_age, 86417}]),
- ok.
-
-cookie_to_iodata_failures_test_() ->
- F = fun(N, V) ->
- try cookie_to_iodata(N, V, []) of
- _ ->
- false
- catch _:_ ->
- true
- end
- end,
- Tests = [
- {<<"Na=me">>, <<"Value">>},
- {<<"Name;">>, <<"Value">>},
- {<<"\r\name">>, <<"Value">>},
- {<<"Name">>, <<"Value;">>},
- {<<"Name">>, <<"\value">>}
- ],
- [{iolist_to_binary(io_lib:format("{~p, ~p} failure", [N, V])),
- fun() -> true = F(N, V) end}
- || {N, V} <- Tests].
-
x_www_form_urlencoded_test_() ->
%% {Qs, Result}
Tests = [
diff --git a/src/cowboy_req.erl b/src/cowboy_req.erl
index 32ff7b0..34302c4 100644
--- a/src/cowboy_req.erl
+++ b/src/cowboy_req.erl
@@ -115,10 +115,7 @@
-export([lock/1]).
-export([to_list/1]).
--type cookie_option() :: {max_age, non_neg_integer()}
- | {domain, binary()} | {path, binary()}
- | {secure, boolean()} | {http_only, boolean()}.
--type cookie_opts() :: [cookie_option()].
+-type cookie_opts() :: cow_cookie:cookie_opts().
-export_type([cookie_opts/0]).
-type content_decode_fun() :: fun((binary())
@@ -430,7 +427,7 @@ parse_header(Name = <<"content-length">>, Req, Default) ->
parse_header(Name = <<"content-type">>, Req, Default) ->
parse_header(Name, Req, Default, fun cowboy_http:content_type/1);
parse_header(Name = <<"cookie">>, Req, Default) ->
- parse_header(Name, Req, Default, fun cowboy_http:cookie_list/1);
+ parse_header(Name, Req, Default, fun cow_cookie:parse_cookie/1);
parse_header(Name = <<"expect">>, Req, Default) ->
parse_header(Name, Req, Default,
fun (Value) ->
@@ -495,10 +492,7 @@ cookie(Name, Req=#http_req{cookies=undefined}, Default) when is_binary(Name) ->
{ok, undefined, Req2} ->
{Default, Req2#http_req{cookies=[]}};
{ok, Cookies, Req2} ->
- cookie(Name, Req2#http_req{cookies=Cookies}, Default);
- %% Flash player incorrectly sends an empty Cookie header.
- {error, badarg} ->
- {Default, Req#http_req{cookies=[]}}
+ cookie(Name, Req2#http_req{cookies=Cookies}, Default)
end;
cookie(Name, Req, Default) ->
case lists:keyfind(Name, 1, Req#http_req.cookies) of
@@ -854,7 +848,7 @@ multipart_skip(Req) ->
-spec set_resp_cookie(iodata(), iodata(), cookie_opts(), Req)
-> Req when Req::req().
set_resp_cookie(Name, Value, Opts, Req) ->
- Cookie = cowboy_http:cookie_to_iodata(Name, Value, Opts),
+ Cookie = cow_cookie:setcookie(Name, Value, Opts),
set_resp_header(<<"set-cookie">>, Cookie, Req).
%% @doc Add a header to the response.