我们的一些用户要求我们在我们发送请求的HTTP 标头中包含与其帐户相关的数据,甚至是我们从 API 获得的响应。在命名 , 格式化等方面添加自定义 HTTP 标头的一般惯例是什么?
另外,您可以随意发布您在网上偶然发现的任何智能用途; 我们正试图用最好的目标来实现这个目标:)
2012 年 6 月,对使用 “X-” 前缀的建议的弃用已成为RFC 6648 的正式版本。以下是相关的引用:
3. 对新参数的创建者的建议
...
- 不应该在其参数名称前加上 “X-” 或类似的结构。
4. 对协议设计者的建议
...
不应禁止注册具有 “X-” 前缀或类似结构的参数。
绝不能规定具有 “X-” 前缀或类似结构的参数需要被理解为非标准化。
绝不能规定没有 “X-” 前缀或类似结构的参数需要被理解为标准化。
请注意,“不应该”(“不鼓励”)与 “必须”(“禁止”)不同,请参阅RFC 2119以获取有关这些关键字的其他规范。换句话说,您可以继续使用 “X-” 前缀标题,但不建议这样做,您也不能将它们记录为公共标准。
2011 年 6 月,发布了第一个IETF 草案 , 弃用了对非标准头文件使用 “X-” 前缀的建议。原因是当前缀为 “X-” 的非标准头文件成为标准时,删除 “X-” 前缀会破坏向后兼容性,迫使应用程序协议支持这两个名称(例如, x-gzip
和gzip
现在是等效的)。所以,建议只是在没有 “X-” 前缀的情况下明智地命名它们。
该建议 是与 “X-” 开始他们的名字。例如X-Forwarded-For
, X-Requested-With
。这也在RFC 2047 的第 5 节中提到。
这个问题需要重新阅读。问题的实际问题与 CSS 属性中的供应商前缀不同,后者在未来的情况下考虑并考虑供应商支持和官方标准。问的实际问题更类似于选择 URL 查询参数名称。没有人应该关心它们是什么。但是,自定义名称间隔是完全有效的 - 并且是常见且正确的 - 要做的事情。
理由:
它是关于开发人员之间关于自定义,特定于应用程序的标题 - “ 与其帐户相关的数据 ” - 与供应商,标准组织或由第三方实施的协议无关的约定 ,除了有问题的开发人员只需要避免服务器,代理或客户端可能具有其他预期用途的标头名称。出于这个原因,给出的 “X-Gzip / Gzip” 和 “X-Forwarded-For / Forwarded-For” 示例没有实际意义。提出的问题是关于私有 API 上下文中的约定,类似于 URL 查询参数命名约定。这是一个偏好和名称间距的问题; 没有 “X” 的任何代理或供应商支持 “X-ClientDataFoo” 的担忧显然是错误的。
关于 “X-” 前缀没有什么特别或神奇之处,但它有助于明确它是一个自定义标题。实际上,RFC-6648 等帮助支持使用 “X-” 前缀的情况,因为 - 当 HTTP 客户端和服务器的供应商放弃前缀 - 您的应用程序特定的私有 API,个人数据 - 传递机制变得更加绝对 - 与少量官方保留标题名称的名称空间冲突隔离。也就是说,我的个人偏好和建议是更进一步,例如 “X-ACME-ClientDataFoo”(如果您的小部件公司是 “ACME”)。
恕我直言,IETF 规范不足以回答 OP 的问题,因为它无法区分完全不同的用例:(A)供应商一方面引入新的全球适用功能,如 “Forwarded-For”,与(B) app 开发人员将特定于应用程序的字符串传递给客户端和服务器。该规范仅涉及前者(A)。这里的问题是(B)是否有惯例。有。它们涉及按字母顺序将参数分组,并将它们与(A)类型的许多标准相关标题分开。使用 “X-” 或“X-ACME-” 前缀对于(B)来说是方便和合法的,并且与(A)不冲突。对于(A),越多的供应商停止使用“X-”,(B)将变得越清晰。
例:
谷歌(在各种标准机构中占有一定的份量)是 - 截至今日,20141102,在我的回答的这个轻微编辑中 - 目前正在使用 “X-Mod-Pagespeed” 来表示其所涉及的 Apache 模块的版本转换给定的响应。是否有人真的建议谷歌应该使用 “Mod-Pagespeed” 而不使用 “X-”,和 / 或要求 IETF 保佑其使用?
摘要:
如果您在应用程序中使用自定义 HTTP 标头(作为有时适合的 cookie 替代方案)来向服务器传送数据或从服务器传递数据,并且这些标头明确地不打算在应用程序的上下文之外使用,使用 “X-” 或 “X-FOO-” 前缀对它们进行名称间隔是一种合理且通用的约定。
HTTP 标头的格式在 HTTP 规范中定义。我将讨论 HTTP 1.1,其规范是RFC 2616 。在第 4.2 节 “消息头” 中,定义了头的一般结构:
message-header = field-name ":" [ field-value ]
field-name = token
field-value = *( field-content | LWS )
field-content = <the OCTETs making up the field-value
and consisting of either *TEXT or combinations
of token, separators, and quoted-string>
该定义基于两个主要支柱:令牌和 TEXT。两者都在第 2.2 节 “基本规则” 中定义。令牌是:
token = 1*<any CHAR except CTLs or separators>
反过来依靠 CHAR,CTL 和分隔符:
CHAR = <any US-ASCII character (octets 0 - 127)>
CTL = <any US-ASCII control character
(octets 0 - 31) and DEL (127)>
separators = "(" | ")" | "<" | ">" | "@"
| "," | ";" | ":" | "\" | <">
| "/" | "[" | "]" | "?" | "="
| "{" | "}" | SP | HT
文字是:
TEXT = <any OCTET except CTLs,
but including LWS>
LWS 是线性空白区域,其定义我不会重现,而 OCTET 是:
OCTET = <any 8-bit sequence of data>
该定义附有说明:
The TEXT rule is only used for descriptive field contents and values
that are not intended to be interpreted by the message parser. Words
of *TEXT MAY contain characters from character sets other than ISO-
8859-1 [22] only when encoded according to the rules of RFC 2047
[14].
那么,有两个结论。首先,很明显,标题名称必须由 ASCII 字符的子集组成 - 字母数字,一些标点符号,而不是其他许多字符串。其次,标题值的定义中没有任何内容将其限制为 ASCII 或排除 8 位字符:它明确地由八位字节组成,仅禁止控制字符(注意 CR 和 LF 被视为控件)。此外,对 TEXT 产生的评论暗示八位字节将被解释为在 ISO-8859-1 中,并且存在用于表示该编码之外的字符的编码机制(这是偶然的,可怕的)。
因此,特别要回应 @BalusC,很明显根据规范,标题值在 ISO-8859-1 中。我已经在 Tomcat 的标题中发送了高 8859-1 个字符(特别是法语中使用的一些重音元音),并且让它们被 Firefox 正确解释,所以在某种程度上,这在实践和理论上都有效。 (虽然这是一个包含 URL 的 Location 标头,这些字符在 URL 中不合法,所以这实际上是非法的,但是在不同的规则下!)。
也就是说,我不会依赖 ISO-8859-1 在所有服务器,代理和客户端上工作,所以我会坚持使用 ASCII 作为防御性编程的问题。