106

在是否要做的问题上,目前的情况是什么

Transfer-Encoding: gzip

或一个

Content-Encoding: gzip

当我想让带宽有限的客户端表示他们愿意接受压缩响应时,服务器拥有是否压缩的最终决定权

后者是例如 Apache 的 mod_deflate 和 IIS 所做的,如果您让它负责压缩。根据要压缩的内容的大小,它会做额外的Transfer-Encoding: chunked.

它还将包括一个Vary: Accept-Encoding,它已经暗示了问题。Content-Encoding似乎是实体的一部分,因此更改Content-Encoding数量等于实体的更改,即不同的Accept-Encoding标头意味着例如缓存不能使用其缓存版本的其他相同实体。

是否有一个我错过的明确答案(并且没有隐藏在某些 apache 新闻组的长线程中的消息中)?

我现在的印象是:

  • Transfer-Encoding 实际上是现有服务器和客户端实现通过 Content-Encoding 完成大部分工作的正确方法
  • ETag内容编码,因为它的语义含义,带来了几个问题(当它透明地压缩响应时,服务器应该做什么?)
  • 原因很简单:浏览器不支持它,因为服务器不支持,因为浏览器不支持

所以我假设正确的方法是 a Transfer-Encoding: gzip(或者,如果我另外分块身体,它会变成 Transfer-Encoding: gzip, chunked)。在这种情况下,没有理由触摸VaryETag任何其他标题,因为它是传输级别的东西。

现在我不太关心 的“逐跳”性Transfer-Encoding,其他人似乎首先关心的是,因为代理可能会解压缩并将未压缩的转发给客户端。但是,如果原始请求具有正确的标头,代理也可以按原样(压缩)转发它,Accept-Encoding在我知道的所有浏览器的情况下都是给定的。

顺便说一句,这个问题至少有十年的历史了,参见例如 https://bugzilla.mozilla.org/show_bug.cgi?id=68517

对此的任何澄清将不胜感激。无论是在什么被认为符合标准和什么被认为是实用方面。例如,仅支持透明“内容编码”的 HTTP 客户端库将成为反对实用性的论据。

4

2 回答 2

36

引用RFC 2616 的作者之一Roy T. Fielding的话:

以不一致的方式动态更改内容编码(“从不”或“总是”)使得以后关于该内容的请求(例如,PUT 或条件 GET)无法正确处理。当然,这就是为什么执行动态内容编码是一个愚蠢的想法,以及为什么我将 Transfer-Encoding 添加到 HTTP 作为在不更改资源的情况下进行动态编码的正确方法。

来源:https ://issues.apache.org/bugzilla/show_bug.cgi?id=39727#c31

换句话说:不要进行即时内容编码,而是使用传输编码!

编辑:也就是说,除非您想将压缩内容提供给只了解 Content-Encoding 的客户端。不幸的是,这似乎是其中的大多数。但是请注意,您离开了规范的领域,可能会遇到诸如 Fielding 和其他人提到的问题,例如在涉及缓存代理时。

于 2012-07-26T07:19:45.120 回答
34

如 RFC 2616 中所定义并在野外实际实现的正确用法是客户端发送Accept-Encoding请求标头(客户端可以指定多种编码)。然后,服务器可以并且仅在那时,根据客户端支持的编码对响应进行编码(如果文件数据尚未存储在该编码中),在Content-Encoding响应标头中指示正在使用哪种编码。然后,客户端可以根据Transfer-Encoding(ie, chunked) 从套接字读取数据,然后根据Content-Encoding(ie: gzip) 对其进行解码。

因此,在您的情况下,客户端将发送一个Accept-Encoding: gzip请求标头,然后服务器可能决定压缩(如果还没有)并发送一个Content-Encoding: gzip可选的Transfer-Encoding: chunked响应标头。

是的,Transfer-Encoding标头可以在请求中使用,但仅适用于 HTTP 1.1,它要求客户端和服务器实现chunked都支持双向编码。

ETag唯一标识服务器上的资源数据,而不是实际传输的数据。如果给定的 URL 资源更改了其ETag值,则意味着该资源的服务器端数据已更改。

于 2013-05-07T02:25:28.977 回答