【问题标题】:How HTTP proxy should handle HEAD requests?HTTP 代理应该如何处理 HEAD 请求?
【发布时间】:2019-06-13 08:01:11
【问题描述】:

RFC7230 中规定的 HTTP/1.1 协议是无状态的,但 HEAD 请求方法应该在客户端和代理中生成一些状态,因为没有其他方法可以确定对 HEAD 请求的响应的消息体长度。

只有两种方法可以确定 HTTP 响应的实际传输长度。它们在 RFC7230 的 3.3.3 中进行了描述。

让我们假设 HTTP 请求管道正在运行,客户端生成一些有效的 HEAD 和 GET 序列到源服务器上的一些现有资源,并且在从客户端到源服务器的路径上有一个透明的 HTTP 代理。

HTTP 协议被定义为无状态,因此在通信的任何部分或协议本身采取的任何操作都不得生成任何状态(不是必须生成某些状态的传输协议,如 TCP 以重新排序消息等)。

如果代理不能记住该请求已完成的事实(不得生成状态),代理应如何识别对客户端 HEAD 请求的原始服务器响应的结束(即消息正文的长度)?

如果代理盲目地解释源服务器响应 HEAD 方法发送的 Content-Length 或 Transfer-Encoding 字段,它将无限期地阻塞等待消息体,因为源服务器永远不会发送消息体。

因此,客户端必须生成一些状态来记住发送的不是 GET 而是 HEAD 请求(因为同样的问题 - 无法确定消息正文长度)。

所以 HEAD 方法本质上是无状态 HTTP 协议中的有状态方法,这是一个矛盾。

更糟糕的是 HEAD 方法必须由任何服务器实现,如 RFC7231 的 4.1 所述,不能以 501 或 405 响应。

这种矛盾使得在 HTTP 代理上实现简单的攻击向量成为可能:用 HEAD 请求混合代理以生成足够的状态来产生内存不足的错误。

我所做的小型研究表明,现代代理将 HEAD 请求交换为 GET 请求,但这会比简单地记住资源路径和请求类型(例如在某些哈希映射中)产生更多的状态和流量。

因此我可以得出结论,HEAD 请求的存在与 HTTP/1.1 协议的无状态性相矛盾。

【问题讨论】:

  • Pesse 解释了为什么您认为 HEAD 请求必须在代理中生成状态。请记住,HEAD 请求不会生成响应正文。
  • @CodeCaster 它在问题描述中得到了准确的解释
  • 我不清楚你的意思是什么“状态”。如果 HEAD 响应包含 Content-Length 标头,那么是的,用户代理(或代理)将记住该请求是 HEAD 请求并且实际上没有正文将跟随。那不是“状态”。
  • @CodeCaster 'Stateless' 意味着协议采取的任何行动在一段时间内不得产生任何要处理的数据(即“状态”)。但是 HEAD 请求需要创建一些关于它的信息并保存它直到重播到达(a.e.'state')
  • 是的,TCP/IP 堆栈会记住连接的“状态”,否则服务器无法回复。这不是 HTTP 的无状态所涉及的那种状态。

标签: http proxy


【解决方案1】:

RFC 规定:

HTTP 被定义为无状态协议,这意味着每个请求 可以单独理解消息。

这并不意味着服务器不能保持任何状态。这并不意味着服务器不能将请求数据保存在内存中,或者保存有关 TCP/IP 连接或请求本身的状态 - 否则它将无法响应。

这只是意味着在不同的请求-响应对之间没有要保留的状态。

【讨论】:

  • 那么你同意像代理这样的中介应该记住客户端声明的请求类型以正确识别响应长度?那么在请求流水线的情况下应该发生什么? BTW TCP 连接或 IP 分片的状态不是 HTTP 协议管理的状态类型,因此不计算在内。
猜你喜欢
  • 2023-03-30
  • 2012-07-28
  • 1970-01-01
  • 2016-03-20
  • 1970-01-01
  • 2011-03-27
  • 2013-06-22
  • 1970-01-01
  • 2011-02-23
相关资源
最近更新 更多