如何设置多个具有相同名称的HTTP头?

76
据我所知,HTTP规范允许设置多个具有相同名称的HTTP头。是否存在使用这样做的用例(从客户端到服务器和反之亦然)? HTTP 1.1第4.2节
多个具有相同字段名称的消息头字段只有在整个字段值被定义为逗号分隔列表时才可以出现在消息中。因此,必须能够将多个头字段组合成一个“field-name: field-value”对,而不改变消息的语义,方法是将每个后续的字段值附加到第一个字段值上,每个字段值之间用逗号分隔。因此,接收具有相同字段名称的标头字段的顺序对于解释组合字段值非常重要,因此代理在转发消息时不得更改这些字段值的顺序。
如果我没错的话,没有需要使用相同名称的多个头的情况。

3
"如果我没记错的话,没有必要使用相同名称的多个标头。"--你说得对,但这并不是一定可以得到支持的事情,这取决于在原始标头和你之间使用了什么技术。" - heisenberg
9
我只在Set-Cookie:这个头部出现过重复的情况。 - TRiG
2
相关问题:是否可以接受重复的HTTP响应头?。WebDAV头部是另一个例子,其中包含了重复的头部名称。 - chrisjleu
实际上,在k8s认证代理中,您不能在单个标头名称中传递逗号分隔的值列表!原因是k8s支持逗号用于RBAC资源名称(出于某种不可思议的原因;可能是遗留错误/疏忽导致的)。 - mecampbellsoup
5个回答

66

这通常用于Set-Cookie:。许多服务器设置多个cookie。

当然,您可以在单个标头中设置所有cookie。

实际上,我认为您不能在一个标头中设置多个cookie。因此,这是必要的用例。

Cookie规范(RFC 2109)确实声称您可以将多个cookie组合在一个标头中,就像其他标头可以组合一样(用逗号分隔),但它还指出,不符合语法的语法(例如Expires参数,在其值中有,)仍然很常见,并且必须由实现处理。

因此,如果您在Set-Cookie标头中使用Expires参数,并且不希望所有cookie同时过期,则可能需要使用多个标头。

更新:Cookie规范的演变

RFC 2109已被RFC 2965取代,后者又被RFC 6265取代,该规范对此问题更加严格:

起始服务器不应将多个"Set-Cookie"头字段折叠成单个头字段。HTTP头字段折叠的通常机制(如[RFC2616]所定义)可能会改变"Set-Cookie"头字段的语义,因为"Set-Cookie"使用%x2C(",")字符的方式与此类折叠冲突。

附注

RFC 6265在引用将多个头字段合并为一个时使用动词“折叠”,这在HTTP / 1规范(由RFC2616及其后继者RFC 7230确定)的上下文中是模棱两可的,其中:

  • “折叠”一直指代行折叠,以及

  • 动词“组合”用于描述合并相同的头。

组合头字段:

请参见RFC 2616,第4.2节,消息头(引用问题中的内容),但搜索“combine”一词将显示特殊情况。
上述项目已被RFC 7230,第3.2.2节,字段顺序所取代:
收件人可以将具有相同字段名称的多个标头字段组合为一个field-name: field-value对,通过按顺序将每个后续字段值附加到组合字段值中,并用逗号分隔,而不改变消息的语义。因此,接收具有相同字段名称的标头字段的顺序对于解释组合字段值非常重要;代理在转发消息时不得更改这些字段值的顺序。
注意:在实践中,“Set-Cookie”标头字段(RFC6265)经常在响应消息中多次出现,并且不使用列表语法,从而违反了具有相同名称的多个标头字段的上述要求。由于它无法合并为单个字段值,因此接收方在处理标头字段时应将Set-Cookie视为特殊情况。(有关详细信息,请参见[Kri2001]的附录A.2.3。)

行折叠:

  • 来自RFC 2616,第2.2节,基本规则

    如果连续行以空格或水平制表符开头,则可以将HTTP/1.1标头字段值折叠到多行上。包括折叠在内的所有线性空白具有与SP相同的语义。接收者可以在解释字段值或向下游转发消息之前将任何线性空白替换为单个SP。

  • 上述部分已被RFC 7230,第3.2.4节,字段解析所取代:

    从历史上看,HTTP标头字段值可以通过在每个额外行之前加上至少一个空格或水平制表符(obs-fold)来扩展多行。除了在媒体类型中(第8.3.1节)以外,此规范不建议使用此类行折叠。发送方不得生成包含行折叠(即具有任何与obs-fold规则匹配的字段值)的消息,除非该消息旨在打包到媒体类型中。

    在请求消息中接收到不在容器中的obs-fold的服务器必须拒绝该消息,最好发送一个400(Bad Request),并解释过时的行折叠是不可接受的,或在解释字段值或向下游转发消息之前将每个接收到的obs-fold替换为一个或多个SP八位字节。

    在响应消息中接收到不在容器中的obs-fold的代理或网关必须丢弃该消息,并用502(Bad Gateway)响应替换它,最好解释已接收到不可接受的行折叠,或在解释字段值或向下游转发消息之前将每个接收到的obs-fold替换为一个或多个SP八位字节。

    在响应消息中接收到不在容器中的obs-fold的用户代理必须在解释字段值之前将每个接收到的obs-fold替换为一个或多个SP八位字节。


您可以轻松地在一个标头中设置它们:Set-Cookie: hello=world; conception=proofed - BronzeByte
3
啊,但是你能在同一个Header中设置不同到期时间的cookies吗?比如说,你能把这个转换成一个header吗? Set-Cookie: name1=value1; Expires=Wed, 22 Feb 2012 17:45:00 GMT Set-Cookie: name2=value2; Expires=Wed, 09 Jun 2021 10:18:14 GMT - sligocki
这将在浏览器中保存一个名为“Expires”的cookie,并被第二个覆盖...同时,我已经构建了一个服务器端的会话后端,100%安全,超级简单且可以保存Java对象。 - BronzeByte
4
不,"Expires"有特殊的含义,就像"Path"、"Secure"、"Domain"等一样(参见http://www.ietf.org/rfc/rfc2109.txt)。例如,查看此页面的HTTP头信息,我看到:"Set-Cookie:usr=t=[redacted]; domain=.stackoverflow.com; expires=Fri, 12-Oct-2012 23:27:03 GMT; path=/; HttpOnly"。我认为这个头信息中设置的所有cookie都必须应用这些限定符(域名、过期时间、路径和HttpOnly)。 - sligocki

16

因为重复的标题可能会影响各种Web服务器和API(无论规范如何),我怀疑在任何通用用例中这都不是最佳实践。当然,这并不是说某个地方没有人这样做。


内容安全策略旨在处理多个头信息。请参阅https://twitter.com/mikewest/status/841892857736765443,了解此问题的原因。 - oreoshake
7
有些标题是打算重复的。自此回答最初发布以来,这些标题(例如“Link”)的数量和普遍性已经增加,但即使在那时,发送多个“Set-Cookie”头部也很常见。 - Zenexer

15

如果你正在寻找用例,也许Accept是一个有效的选项。

  • 接受:application/json
  • 接受:application/xml

11

他在问题中非常清楚地表明了他意识到这是允许的,这不是他要问的。 - heisenberg
12
那个链接非常有帮助,特别是提到重复出现的标题必须能够表示为一个具有逗号分隔值的单个标题的部分。 - nategood

1

虽然这是一个旧的帖子,但我也在研究同样的问题。无论如何,Accept和Accept-Encoding头文件都是使用多个值的典型示例,以逗号分隔。即使这些是特定于请求的头文件,规范在此级别上也没有区分请求和响应之间的区别。请查看此页面中的规范。 规范所说的是,如果您在头文件的值中使用逗号作为字符,则不能使用相同名称的多个头文件,除非您消除了逗号的使用歧义。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接