Browse Source

Do not remove duplicated Set-Cookie entries

This commit closes #195, closes #199, closes #246.
José Valim 12 years ago
parent
commit
0d0b962f03
1 changed files with 32 additions and 0 deletions
  1. 32 0
      src/cowboy_req.erl

+ 32 - 0
src/cowboy_req.erl

@@ -1138,8 +1138,18 @@ response_merge_headers(Headers, RespHeaders, DefaultHeaders) ->
 
 
 -spec merge_headers(cowboy_http:headers(), cowboy_http:headers())
 -spec merge_headers(cowboy_http:headers(), cowboy_http:headers())
 	-> cowboy_http:headers().
 	-> cowboy_http:headers().
+
+%% Merge headers by prepending the tuples in the second list to the
+%% first list. It also handles Set-Cookie properly, which supports
+%% duplicated entries. Notice that, while the RFC2109 does allow more
+%% than one cookie to be set per Set-Cookie header, we are following
+%% the implementation of common web servers and applications which
+%% return many distinct headers per each Set-Cookie entry to avoid
+%% issues with clients/browser which may not support it.
 merge_headers(Headers, []) ->
 merge_headers(Headers, []) ->
 	Headers;
 	Headers;
+merge_headers(Headers, [{<<"set-cookie">>, Value}|Tail]) ->
+  merge_headers([{<<"set-cookie">>, Value}|Headers], Tail);
 merge_headers(Headers, [{Name, Value}|Tail]) ->
 merge_headers(Headers, [{Name, Value}|Tail]) ->
 	Headers2 = case lists:keymember(Name, 1, Headers) of
 	Headers2 = case lists:keymember(Name, 1, Headers) of
 		true -> Headers;
 		true -> Headers;
@@ -1333,4 +1343,26 @@ connection_to_atom_test_() ->
 	[{lists:flatten(io_lib:format("~p", [T])),
 	[{lists:flatten(io_lib:format("~p", [T])),
 		fun() -> R = connection_to_atom(T) end} || {T, R} <- Tests].
 		fun() -> R = connection_to_atom(T) end} || {T, R} <- Tests].
 
 
+merge_headers_test() ->
+  Left0  = [{<<"content-length">>,<<"13">>},{<<"server">>,<<"Cowboy">>}],
+  Right0 = [{<<"set-cookie">>,<<"foo=bar">>},{<<"content-length">>,<<"11">>}],
+
+  ?assertMatch(
+  [{<<"set-cookie">>,<<"foo=bar">>},
+   {<<"content-length">>,<<"13">>},
+   {<<"server">>,<<"Cowboy">>}],
+  merge_headers(Left0, Right0)),
+
+  Left1  = [{<<"content-length">>,<<"13">>},{<<"server">>,<<"Cowboy">>}],
+  Right1 = [{<<"set-cookie">>,<<"foo=bar">>},{<<"set-cookie">>,<<"bar=baz">>}],
+
+  ?assertMatch(
+  [{<<"set-cookie">>,<<"bar=baz">>},
+   {<<"set-cookie">>,<<"foo=bar">>},
+   {<<"content-length">>,<<"13">>},
+   {<<"server">>,<<"Cowboy">>}],
+  merge_headers(Left1, Right1)),
+
+  ok.
+
 -endif.
 -endif.