自定义 HTTP 标头:命名约定

我们的几个用户要求我们在发送给他们的请求甚至是从 API 中获得的响应的HTTP 标头中包含与他们的帐户有关的数据。就命名格式等而言,添加自定义 HTTP 标头的一般约定是什么?

另外,请随时在网上发布您偶然发现的这些内容的精巧用法。我们正在尝试使用最好的目标来实现这一目标:)

答案

建议 与 “X-” 开始他们的名字。例如, X-Forwarded-ForX-Requested-WithRFC 2047 的第 5 节也提到了这一点。


更新 1 :2011 年 6 月,发布了IETF的第一稿 ,以弃用对非标准标头使用 “X-” 前缀的建议。原因是当以 “X-” 为前缀的非标准头成为标准头时,删除 “X-” 前缀会破坏向后兼容性,从而迫使应用程序协议同时支持这两个名称(例如, x-gzipgzip现在等效)。因此,官方建议是合理地命名它们,不要使用 “X-” 前缀。


更新 2 :从 2012 年 6 月开始,不再推荐使用 “X-” 前缀作为RFC 6648 。以下是相关的引用:

3. 给新参数创建者的建议

...

  1. 不应在参数名称前加上 “X-” 或类似的结构。

4. 给协议设计者的建议

...

  1. 不应禁止注册带有 “X-” 前缀或类似结构的参数。

  2. 绝对不要规定前缀为 “X-” 或类似结构的参数应理解为非标准化的。

  3. 不得规定没有 “X-” 前缀或类似构造的参数应理解为标准化的。

请注意,“SHOULD NOT”(“禁止使用”)与 “MUST NOT”(“禁止”)不同,另请参阅RFC 2119,以获取有关这些关键字的另一种说明。换句话说,您可以继续使用带有 “X-” 前缀的标头,但是现在不再正式推荐它,并且您可能绝对不会像公开标准那样记录它们。


总结

  • 官方建议是合理地命名它们,不要使用 “X-” 前缀
  • 您可以继续使用带前缀 “X-” 的标头,但现在不再正式建议这样做,并且您绝对不能像公开标准那样记录它们

该问题需要重读。提出的实际问题与 CSS 属性中的供应商前缀不同,在 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)应用程序开发人员将特定于应用程序的字符串传递到客户端和服务器 / 从客户端和服务器传递。规格仅涉及前者(A)。这里的问题是(B)是否有约定。有。它们涉及按字母顺序将参数分组在一起,并将其与类型(A)的许多与标准相关的标头分开。对于(B),使用 “X-” 或“X-ACME-” 前缀是方便且合法的,并且与(A)不冲突。供应商停止在(A)中使用 “X-” 的厂商越多,(B)的供应商的区分就越清晰。

例:
Google(在各个标准机构中都担负着重要的职责)-截止到今天,20141102,对我的回答作了一些细微的修改-目前使用 “X-Mod-Pagespeed” 来指示其所涉及的 Apache 模块的版本转换给定的响应。是否有人真的建议 Google 使用不带 “X-” 的 “Mod-Pagespeed”,和 / 或要求 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>

此定义基于两个主要支柱,令牌和文本。两者均在第 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 是:

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 正确解释了它们,因此在某种程度上,无论是在理论上还是在实践上, (尽管这是一个 Location 标头,其中包含一个 URL,并且这些字符在 URL 中不合法,因此实际上是非法的,但是要遵循不同的规则!)。

就是说,我不会依赖于在所有服务器,代理和客户端上工作的 ISO-8859-1,因此出于防御性编程的考虑,我会坚持使用 ASCII。

RFC6648建议您假定自定义标头 “可能会标准化,公开,普遍部署或在多个实现中可用”。因此,建议不要在其前面加上 “X-” 或类似的结构。

但是,有一个例外 “当 [您的标头] 极不可能被标准化时”。对于此类 “特定于实现和私有使用” 的标头,RFC 表示使用诸如供应商前缀之类的名称空间是合理的。

修改(或更正确地说, 添加其他 HTTP 标头)是一个很棒的代码调试工具,如果没有其他要求的话。

当 URL 请求返回重定向或图像时,没有 html“页面” 可将调试代码的结果临时写入 - 至少在浏览器中不可见。

一种方法是将数据写入本地日志文件,然后再查看该文件。另一个方法是临时添加 HTTP 标头,以反映要调试的数据和变量。

我定期添加额外的 HTTP 标头,例如 X-fubar-somevar:或 X-testing-someresult:进行测试 - 并发现了很多本来很难跟踪的错误。

标头字段名称注册表在RFC3864 中定义,“X-” 没什么特别的。

据我所知,没有私有标头的准则。如有疑问,请避免使用。或查看 HTTP 扩展框架( RFC 2774 )。

了解更多的用例将会很有趣;为什么不能将信息添加到邮件正文中?