aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/src/manual/cowboy_req.set_resp_headers.asciidoc15
-rw-r--r--src/cowboy_req.erl17
-rw-r--r--test/handlers/resp_h.erl13
-rw-r--r--test/req_SUITE.erl10
4 files changed, 48 insertions, 7 deletions
diff --git a/doc/src/manual/cowboy_req.set_resp_headers.asciidoc b/doc/src/manual/cowboy_req.set_resp_headers.asciidoc
index 63fe424..9ca5901 100644
--- a/doc/src/manual/cowboy_req.set_resp_headers.asciidoc
+++ b/doc/src/manual/cowboy_req.set_resp_headers.asciidoc
@@ -11,7 +11,7 @@ cowboy_req:set_resp_headers - Set several response headers
set_resp_headers(Headers, Req :: cowboy_req:req())
-> Req
-Headers :: cowboy:http_headers()
+Headers :: cowboy:http_headers() | [{binary(), iodata()}]
----
Set several headers to be sent with the response.
@@ -32,8 +32,16 @@ instead of this function to set cookies.
Headers::
-Headers as a map with keys being lowercase binary strings,
-and values as binary strings.
+Headers as a map with names being lowercase binary strings,
+and values as iodata; or as a list with the same requirements
+for names and values.
++
+When a list is given it is converted to its equivalent map,
+with duplicate headers concatenated with a comma inserted
+in-between. Support for lists is meant to simplify using
+data from clients or other applications.
++
+The set-cookie header must not be set using this function.
Req::
@@ -48,6 +56,7 @@ otherwise the headers will not be sent in the response.
== Changelog
+* *2.13*: The function now accepts a list of headers.
* *2.0*: Function introduced.
== Examples
diff --git a/src/cowboy_req.erl b/src/cowboy_req.erl
index 8d8cf82..adee364 100644
--- a/src/cowboy_req.erl
+++ b/src/cowboy_req.erl
@@ -726,8 +726,10 @@ set_resp_header(Name, Value, Req=#{resp_headers := RespHeaders}) ->
set_resp_header(Name,Value, Req) ->
Req#{resp_headers => #{Name => Value}}.
--spec set_resp_headers(cowboy:http_headers(), Req)
+-spec set_resp_headers(cowboy:http_headers() | [{binary(), iodata()}], Req)
-> Req when Req::req().
+set_resp_headers(Headers, Req) when is_list(Headers) ->
+ set_resp_headers_list(Headers, Req, #{});
set_resp_headers(#{<<"set-cookie">> := _}, _) ->
exit({response_error, invalid_header,
'Response cookies must be set using cowboy_req:set_resp_cookie/3,4.'});
@@ -736,6 +738,19 @@ set_resp_headers(Headers, Req=#{resp_headers := RespHeaders}) ->
set_resp_headers(Headers, Req) ->
Req#{resp_headers => Headers}.
+set_resp_headers_list([], Req, Acc) ->
+ set_resp_headers(Acc, Req);
+set_resp_headers_list([{<<"set-cookie">>, _}|_], _, _) ->
+ exit({response_error, invalid_header,
+ 'Response cookies must be set using cowboy_req:set_resp_cookie/3,4.'});
+set_resp_headers_list([{Name, Value}|Tail], Req, Acc) ->
+ case Acc of
+ #{Name := ValueAcc} ->
+ set_resp_headers_list(Tail, Req, Acc#{Name => [ValueAcc, <<", ">>, Value]});
+ _ ->
+ set_resp_headers_list(Tail, Req, Acc#{Name => Value})
+ end.
+
-spec resp_header(binary(), req()) -> binary() | undefined.
resp_header(Name, Req) ->
resp_header(Name, Req, undefined).
diff --git a/test/handlers/resp_h.erl b/test/handlers/resp_h.erl
index 6e9b5f7..61f714f 100644
--- a/test/handlers/resp_h.erl
+++ b/test/handlers/resp_h.erl
@@ -43,12 +43,25 @@ do(<<"set_resp_headers">>, Req0, Opts) ->
<<"content-encoding">> => <<"compress">>
}, Req0),
{ok, cowboy_req:reply(200, #{}, "OK", Req), Opts};
+do(<<"set_resp_headers_list">>, Req0, Opts) ->
+ Req = cowboy_req:set_resp_headers([
+ {<<"content-type">>, <<"text/plain">>},
+ {<<"content-encoding">>, <<"compress">>}
+ ], Req0),
+ {ok, cowboy_req:reply(200, #{}, "OK", Req), Opts};
do(<<"set_resp_headers_cookie">>, Req0, Opts) ->
ct_helper:ignore(cowboy_req, set_resp_headers, 2),
Req = cowboy_req:set_resp_headers(#{
<<"set-cookie">> => <<"name=value">>
}, Req0),
{ok, cowboy_req:reply(200, #{}, "OK", Req), Opts};
+do(<<"set_resp_headers_list_cookie">>, Req0, Opts) ->
+ ct_helper:ignore(cowboy_req, set_resp_headers_list, 3),
+ Req = cowboy_req:set_resp_headers([
+ {<<"set-cookie">>, <<"name=value">>},
+ {<<"set-cookie">>, <<"name2=value2">>}
+ ], Req0),
+ {ok, cowboy_req:reply(200, #{}, "OK", Req), Opts};
do(<<"set_resp_headers_http11">>, Req0, Opts) ->
Req = cowboy_req:set_resp_headers(#{
<<"connection">> => <<"custom-header, close">>,
diff --git a/test/req_SUITE.erl b/test/req_SUITE.erl
index f6208a2..0ea1f96 100644
--- a/test/req_SUITE.erl
+++ b/test/req_SUITE.erl
@@ -858,11 +858,15 @@ set_resp_header(Config) ->
set_resp_headers(Config) ->
doc("Response using set_resp_headers."),
- {200, Headers, <<"OK">>} = do_get("/resp/set_resp_headers", Config),
- true = lists:keymember(<<"content-type">>, 1, Headers),
- true = lists:keymember(<<"content-encoding">>, 1, Headers),
+ {200, Headers1, <<"OK">>} = do_get("/resp/set_resp_headers", Config),
+ true = lists:keymember(<<"content-type">>, 1, Headers1),
+ true = lists:keymember(<<"content-encoding">>, 1, Headers1),
+ {200, Headers2, <<"OK">>} = do_get("/resp/set_resp_headers_list", Config),
+ true = lists:keymember(<<"content-type">>, 1, Headers2),
+ true = lists:keymember(<<"content-encoding">>, 1, Headers2),
%% The set-cookie header is special. set_resp_cookie must be used.
{500, _, _} = do_maybe_h3_error3(do_get("/resp/set_resp_headers_cookie", Config)),
+ {500, _, _} = do_maybe_h3_error3(do_get("/resp/set_resp_headers_list_cookie", Config)),
ok.
resp_header(Config) ->