-
Notifications
You must be signed in to change notification settings - Fork 600
Description
Hey there,
While I was working with the Server-Timing header for Phoenix, I stumbled across the fact that Plug does not allow to set the same header twice.
Given the following comment, I assume this behavior is intended.
Adds a new response header (
key
) if not present, otherwise replaces the previous value of that header withvalue
.
-- https://github.com/elixir-plug/plug/blob/master/lib/plug/conn.ex#L626-L627
I think to not support this at all is problematic as the RFC states
A sender MUST NOT generate multiple header fields with the same field name in a message unless either the entire field value for that header field is defined as a comma-separated list [i.e., #(values)] or the header field is a well-known exception (as noted below).
I want to emphasize the last part of the sentence: or the header field is a well-known exception.
These exceptions are not defined anywhere, the RFC talks about Set-Cookie
but there may be more. For example, I was recently working with the Server-Timing API https://w3c.github.io/server-timing/ which allows having the same header twice.
To reproduce
# some phoenix controller
def index(conn, _params) do
conn = Plug.Conn.put_resp_header(conn, "via", "Value A")
conn = Plug.Conn.put_resp_header(conn, "via", "Value B")
render conn, "index.html"
end
Expected behavior
$~ curl -I http://localhost:4000/
HTTP/1.1 200 OK
server: Cowboy
date: Wed, 14 Feb 2018 09:54:22 GMT
content-length: 1932
content-type: text/html; charset=utf-8
cache-control: max-age=0, private, must-revalidate
x-request-id: 146acnn1n4p1bc2ggh4b3rejp3t6m6ce
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
via: Value A
via: Value B
Actual behavior
$~ curl -I http://localhost:4000/
HTTP/1.1 200 OK
server: Cowboy
date: Wed, 14 Feb 2018 09:54:22 GMT
content-length: 1932
content-type: text/html; charset=utf-8
cache-control: max-age=0, private, must-revalidate
x-request-id: 146acnn1n4p1bc2ggh4b3rejp3t6m6ce
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
via: Value B
I did not find any similar issue, even though I thought this may have been discussed before. If I missed it, I am deeply sorry!