传输编码:gzip与内容编码:gzip


98

关于是否要做事,目前的状况是什么

Transfer-Encoding: gzip

或一个

Content-Encoding: gzip

当我要允许带宽有限的客户表示他们愿意接受压缩响应并且服务器最终决定是否压缩时

后者就是例如Apache的mod_deflate和IIS所做的,如果让它负责压缩的话。根据要压缩的内容的大小,它将执行额外的操作Transfer-Encoding: chunked

它还将包含一个Vary: Accept-Encoding,已经暗示了该问题。Content-Encoding似乎是实体的一部分,因此将Content-Encoding金额更改为实体的变化,即,不同的Accept-Encoding标头意味着例如缓存无法使用其在其他方面相同的实体的缓存版本。

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

我目前的印象是:

  • 实际上,传输编码将是正确完成现有服务器和客户端功能的内容编码的正确方法
  • 由于内容编码的语义含义,它带来了两个问题(服务器ETag透明压缩响应时,服务器应该如何处理?)
  • 原因是“鸡蛋”:浏览器不支持它,因为服务器不支持,因为浏览器不支持

因此,我假设正确的方法是Transfer-Encoding: gzip(或者,如果我另外对主体进行分块,它将变成 Transfer-Encoding: gzip, chunked)。在这种情况下,没有理由触摸VaryETag任何其他标头,因为这是传输级的事情。

目前,我不太在乎的“逐跳”性质Transfer-Encoding,这是其他人首先关注的问题,因为代理可能会解压缩并转发给客户端。但是,如果原始请求具有正确的Accept-Encoding标头,则代理可能会按原样转发(压缩)它,对于我所知道的所有浏览器来说,都是给定的。

顺便说一句,这个问题至少存在十年了,请参阅例如 https://bugzilla.mozilla.org/show_bug.cgi?id=68517

任何对此的澄清将不胜感激。无论是从符合标准的方面还是从实用性方面而言。例如,仅支持透明“ Content-Encoding”的HTTP客户端库可能会反对实用性。



刚遇到这个。PHP 5.3上的Curl无法理解Transfer-Encoding:gzip,尽管命令行curl可以。为了安全起见,请同时发送两者,除非您要结合使用chunk和gzip。
塞瓦·阿列克谢耶夫

1
@SevaAlekseyev发送这两个消息将是非常错误的-客户可能会尝试解压缩两次
Joshua Wise

这也是让我永远困扰的事情(我问的问题)……根据@JoLiss引用的问题的答案之一,有一种完美的逻辑,语义上一致且符合标准的方式来压缩请求/响应主体……基本上没有客户端/服务器使用或支持它。
丹·

Answers:


35

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

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

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

换句话说:不要进行即时的 Content-Encoding,而要使用Transfer-Encoding!

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


3
因此,如果我理解正确,请执行以下操作:1.内容编码是抽象地指服务器上的内容编码,即,内容将始终由服务器以指定的编码方式提供。2.传输编码是指服务器在这种情况下(即在此响应中)决定用于将其交付给用户代理的编码。只是确保我不会误解您的答案。
dot slash hack

30
@KemHeyndels关于正确。换句话说,根据规范,Transfer-Encoding是纯传输层详细信息,即中间代理可以随意撤消例如该级别的gzip压缩,而Content-Encoding是业务层属性,而代理不会除了其他分支(ETag等)之外,还允许更改。但是,根据现实情况,TE通常不用于压缩,许多服务器/客户端甚至都不是开箱即用的,而CE或多或少地以TE的使用方式使用:作为传输层细节。
尤金·别列索夫斯基

1
因此,我们有义务不顾Roy T. Fielding的建议?
dot slash hack

11
@KemHeyndels理想主义使您不得不出去,并首先将TE支持添加到所有开源HTTP客户端/服务器实现中。然后,在所有拥有闭源HTTP实现的公司中任职(无论如何我都认为这是Microsoft),并在那里添加功能。在那之后,现实和规格将重合。;)(并且HTTP 2.0将已经发布,无论如何该问题都会消失)
Eugene Beresovsky 2014年

10
表示您支持Transfer-Encoding仍不能明确表明您支持gzip over Transfer-Encoding,因此不会为您带来任何好处。指示是通过另一种方式完成的:任何可以通过Transfer-Encoding执行gzip的客户端都将通过设置让服务器知道TE: gzip。然后,您的服务器应采用“传输编码”路由。如果客户只说了Accept-Encoding: gzip,您就必须这样做Content-Encoding。如果客户端在其请求中均未指定,则服务器根本不能gzip。
尤金·别列索夫斯基

27

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

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

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

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


14
内容编码是由Request-URI标识的实体的特征。换句话说:不同Content-Encoding需要不同ETag这就是我在回答中提到的mod_deflate错误的全部。让我想知道为什么此应用程序级详细信息首先出现在HTTP标准中。当使用Transfer-Encoding然而,传输电平设置,没有必要改变ETag。除非没有人实现Transfer-Enc。
尤金·别列索夫斯基

2
内容编码不适用于“即时”编码。RFC 2616说:“传输编码...与内容编码不同,因为传输编码是消息的属性,而不是实体的属性。”(tools.ietf.org/html/rfc2616#section-14.41),以及“内容编码是由Request-URI标识的实体的特征。通常,实体-主体使用此编码存储”(tools.ietf.org/html/rfc2616#section-14.11)。所以我投了反对票。
罗伯特

我所描述的是“ 实际上是在野外实现的 ”,而与Content-Encodingvs 无关Transfer-Encoding。是的,如果即时完成,gzip 应该是资源传输的属性。另一方面,如果资源以压缩方式存储在服务器上,则应按原样发送,而是资源内容的属性。但是应该是什么和实际上不是总是一回事。
雷米·勒博
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.