【问题标题】:Under what conditions are HTTP request headers removed by proxies?代理在什么情况下会删除 HTTP 请求标头?
【发布时间】:2025-12-05 03:30:01
【问题描述】:

我正在研究 RESTful 版本控制 API 的各种方法,其中有三个主要的竞争者。我相信我已经决定使用X-API-Version。撇开争论不谈,反对使用该标头和自定义标头的论据之一是您无法控制标头何时由代理服务器操作。我很好奇有哪些现实世界的例子,什么时候发生在整个互联网上,什么时候可能用于 Intranet 或服务器集群,或者什么时候可能发生在任何其他情况下。

【问题讨论】:

  • 我不确定我是否愿意依赖人们对“一般情况”的看法。代理可以对您的标头做任何它喜欢的事情 - 我不知道任何经验法则或公认的行为。你的版本控制是为了什么?人们可以选择不同的版本吗?还是标题只是为了提供信息?如果它用于选择版本,我会亲自将版本号作为 URL 的一部分。
  • 我在其他地方听到过意见——我找不到任何真实世界中实际删除或更改标头的示例(除了旨在由代理操纵的标头,例如 Via)。
  • 不相关,但使用标头对 API 进行版本控制并不是一个好习惯。 mnot.net/blog/2012/07/11/header_versioning
  • @Mark 是的,我读过那个。其他 S.O. 上有很好的讨论和链接。问题。但我不明白你的论点,即必须使用“Vary”是一种不好的代码气味。我恭敬地拒绝您的结论,即使用标头进行版本控制是不好的;)

标签: api http rest language-agnostic rfc2616


【解决方案1】:

这本身不是一个答案,而是对现实世界场景的提及。

我当前的环境使用混合 CAS/AD 解决方案,以允许跨多个不同平台(经典 ASP、ASP.NET、J2EE 等等)的 SSO。

最近我们发现了一些问题 - 部分解决方案涉及在必要时将 Auth 令牌聚合到 HTTP 标头以传播凭据。一个特定的解决方案,大量使用 cookie,与 nginx 实现链接,其 HTTP 标头限制设置为 4KiB。如果 cookie 有效负载超过 2KiB,它将开始泄漏标头。

因此,通过 HTTP 标头(包括会话 cookie)协调某种状态/范围控制的应用程序突然开始出现异常行为。

在一个有趣的相关说明中,使用 URL 版本控制(例如http://server/api/vX.X/resource)的 REST 服务不受影响。

【讨论】:

  • 好的,很有趣...如此大的标题或较小的最大尺寸可能是导致问题的一个因素。
  • 正确,@wprl - 或者,换句话说,依赖于标头的 API 可能会因看似无关的框架问题而遭受附带损害。
  • 标头中支持和反对 API 版本控制的论点已在其他地方提出 :) 我想知道的是操纵标头时的实际情况,就像您已经很友善地给出了一样。到目前为止,这是我能找到的唯一例子。
【解决方案2】:

Guidelines for Web Content Transformation Proxies 1.0 几乎是理解和预测符合标准的代理服务器行为的权威指南。就您的问题而言,文档的Proxy Forwarding of Request 部分可能特别有用。

每个代理软件包及其各自的配置都会有所不同,但 HTTP 代理通常应遵循 W3C 指南。以下是一些亮点。

4.1 请求的代理转发

除了在 HEAD 和 GET 代理之间进行转换外,不得更改请求方法。

如果请求包含 Cache-Control: no-transform 指令,则代理不得更改请求,除非遵守 [RFC 2616 HTTP] 第 14.9.5 节和第 13.5.2 节中定义的透明 HTTP 行为,并且按照下面的 4.1.6 附加 HTTP 标头字段中的说明添加标头字段。

4.1.3 对非 Web 浏览器的请求者的处理

在更改 HTTP 请求和响应的各个方面之前,代理需要考虑这样一个事实,即 HTTP 被用作“传统浏览”以外的许多应用程序的传输机制。越来越多的基于浏览器的应用程序涉及使用 XMLHttpRequest 进行数据交换(请参阅 4.2.8 转换的代理决策),并且更改此类交换可能会导致误操作。

4.1.5 HTTP 标头字段值的更改

除了 [RFC 2616 HTTP] 要求的修改之外,代理不应修改 User-AgentAccept 以外的标头字段的值strong>、Accept-CharsetAccept-EncodingAccept-Language 标头字段并且不得删除标头字段(请参阅 4.1.5.5 原始标题字段)。

除了遵守透明的 HTTP 操作外,代理不应修改任何请求头字段,除非以下情况之一适用:

  • 由于服务器响应请求“不可接受”,用户将被禁止访问内容(请参阅 4.2.4 服务器拒绝 HTTP 请求);

  • 用户已明确请求重构的桌面体验(请参阅 4.1.5.3 重构体验的用户选择);

  • 请求是一系列请求的一部分,包括同一网站上的包含资源或链接资源(请参阅 4.1.5.4 请求序列)。

这些情况将在以下部分详细说明。

注意:

需要强调的是,在存在 Cache-Control: no-transform 的情况下不得更改请求,如 4.1.2 请求中的 no-transform 指令所述。

请求中引用的 URI 在确定是否更改 HTTP 请求标头字段值方面没有任何作用。特别是 4.2.8 Proxy Decision to Transform 中提到的模式并不重要。

4.1.6 附加 HTTP 标头字段

无论是否存在非转换指令:

  • 代理应将请求发起者的 IP 地址添加到 X-Forwarded-For HTTP 标头字段中逗号分隔列表的末尾;

  • 代理必须(根据 RFC 2616)包含 Via HTTP 头字段(请参阅 4.1.6.1 Via 头字段的代理处理)。


还有很多关于响应标头更改以及能够检测到这些更改的信息。

关于 Web 服务 REST API 版本控制,Best practices for API versioning? 有一个非常清晰和有用的 SO 线程,它应该提供大量有用的见解。

我希望所有这些都会有所帮助。保重。

【讨论】:

  • 非常感谢,这是最突出的!我同意关于最佳实践的 SO 线程非常好。根据额外的阅读材料和我自己对 REST API 设计的见解,我得出了与最佳答案不同的结论。
最近更新 更多