分块编码响应的gzip压缩?

41

我正在尝试让我的Web服务器正确地对分块编码的http响应进行gzip压缩。

我对非gzip响应的理解是它看起来像这样:

<the response headers>

接着,对于每个块,

<chunk length in hex>\r\n<chunk>\r\n

最后,一个长度为零的块:

0\r\n\r\n

我尝试启用gzip压缩,但需要帮助弄清楚应该返回什么内容。这份文档暗示着整个响应应该被gzip压缩,而不是压缩每个数据块:

HTTP servers sometimes use compression (gzip) or deflate methods to optimize transmission.
Chunked transfer encoding can be used to delimit parts of the compressed object.
In this case the chunks are not individually compressed. Instead, the complete payload 
is compressed and the output of the compression process is chunk encoded.

我试图对整个内容进行gzip压缩并返回响应,即使不使用分块传输也不起作用。 我尝试将Content-Encoding标头设置为"gzip"。 有人能解释一下必须对上述方案进行哪些更改以支持分块的gzipping吗? 谢谢。

3个回答

41

如果其他回答不够清晰:

首先使用zlib压缩正文(这可以通过流完成,因此您不需要一次性将所有数据存储在内存中,这就是分块的全部目的)。

然后用Content-Encoding: gzip和Transfer-Encoding: chunked标头(没有Content-Length标头),将该压缩正文分块发送(假定由gzip流提供的块带有声明其长度的块标头)。

如果您使用gzip或zcat或类似实用程序进行压缩,则可能无法正常工作。 需要使用zlib。 如果您创建块,然后再对其进行压缩,那肯定不行。 如果您认为自己做得对但出现问题,请尝试进行包跟踪并根据任何错误消息提出问题。



29
您需要先对内容进行gzip压缩,然后再应用分块编码:
“由于“分块”是HTTP/1.1接收方必须理解的唯一传输编码,因此它在在持久连接上限定消息的角色非常重要。每当在请求的有效负载中应用传输编码时,最终应该应用“分块”传输编码。如果响应有效负载体应用传输编码,则最终应该应用“分块”传输编码,或者通过关闭连接来终止消息。当使用“分块”传输编码时,它必须是形成消息主体所应用的最后一个传输编码。“分块”传输编码不得在消息主体中应用多次。”
(引用自:HTTPbis Part1, Section 6.2.1

2
这段程序相关的内容有些晦涩难懂,我认为应该做出修改……你需要对每个数据块的主体进行gzip压缩(我刚刚实现了这个功能,且取得了很好的效果)。你不能先对整个内容进行gzip压缩,然后再使用分块编码。你需要对每个主体进行gzip压缩,并标记压缩后的字节数组大小作为数据块大小。 - Dean Hiller
HTTP/1.1 定义了三种区分消息结束和下一条消息开始的方式(HTTP 管线化、持久连接):内容长度头、传输编码头,如果以上两者都不存在,则最低优先级是关闭连接。 - малин чекуров

1

很可能您没有发送适当的gzip响应。

尝试在zlib中将window bits设置为31。并使用deflateInit2()


1
这对实现做了一些假设。如果他只是使用“gzip”命令压缩文件并返回该文件,同时设置Content-Encoding: gzip头,那么会产生相同的输出吗? - sosiouxme
HTTP标准确实需要使用zlib库。gzip命令将输出更多的头信息,但这应该与大多数其他HTTP客户端/服务器中使用的zlib兼容。 - unixman83
更有可能的是,发布者没有设置“Content-Length”头或不正确地发送了分块响应。或者是忘记在标头之后添加基本的尾随换行符。 - unixman83
1
如果他发送的是分块数据,那么就不应该有Content-Length头部。当然,在他发送非分块数据且“没有工作”的情况下,Content-Length会被需要。发帖者可能更有助于了解他遇到的问题,因为他的理解至少是正确的。考虑到这个问题是在三月份发出的,他很可能早已解决或放弃了。最近我必须实现这个功能,我认为用gzip压缩文件并传输它并没有起作用。你提供的关于在zlib中设置window bits为31的建议非常有帮助,谢谢。 - sosiouxme

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接