Tomcat压缩gzip和分块传输问题

6

我遇到了一个数据源服务的问题。根据HTTP响应头部所显示的,它正在运行Apache-Coyote/1.1版本。服务器以分块方式传输响应,下面是一个样例响应:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/xml;charset=utf-8
Transfer-Encoding: chunked
Content-Encoding: gzip
Date: Tue, 30 Mar 2010 06:13:52 GMT

当我请求服务器发送压缩请求时,问题在于它经常发送不完整的响应。我收到了响应,看到最后一个块被接收,但是解压后发现响应是部分的。在请求头关闭gzip时,我从未见过这样的行为。
所以我的问题是:这是常见的Tomcat问题吗?也许是其中一个进行压缩的模块?或者可能是某种代理问题?我无法确定Tomcat的版本或使用的gzip模块,但请随意询问,我会尝试问我的服务提供商。
谢谢。

你使用的是哪个客户端/库来发起请求? - Asaph
你能发布你的请求头吗? - Asaph
我正在使用自己的部分HTTP实现,因为我说过它可以很好地处理没有gzip编码的情况,并且在大多数情况下对于gzipped也能很好地工作,但是大约有30%的gzipped响应在解压缩后都是垃圾!我的请求如下:POST http://example.com/Service HTTP/1.1 Content-Length: 1081 Content-Encoding: gzip Accept-Encoding: gzip Host: example.com User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 1.0.3705) Authorization: Basic UENDN0IySjpTb3KxdWE3YjJq SOAPAction: http://example.com/Service// 这里是我的压缩请求... - hoodoos
1个回答

3
由于压缩后响应内容的长度不可预测,而且在内存中完全压缩它并计算长度,然后从内存中流式传输压缩后的响应可能会非常昂贵和缓慢,因此普通的Web服务器将使用Transfer-Encoding:chunked以分块形式发送它们,没有Content-Length头部。
由于它是自制的HTTP客户端,似乎无法正确处理分块请求。您必须确定Transfer-Encoding响应头,如果等于chunked,则必须将其解析为分块流。
你可以从上述HTTP规范链接和维基百科中学习如何解析分块流。每个块都由一个标题组成,以十六进制表示块长度,然后是CRLF,接着是实际的块内容,再是CRLF。这将重复进行,直到具有标头指示块长度为0的块。您需要单独解压缩这些块,然后将它们粘合在一起。
为了节省所有繁琐的编码工作(很可能也适用于您自己开发的HTTP客户端的剩余部分),我强烈建议您查看Apache HttpComponents Client

它在其他网站上完美运行,如果我关闭gzipping,它也可以与此服务一起使用。我实际上在我的工作机器上安装了tomcat,有时也无法提供内容。我很高兴认为这是我的问题,但如果我使用.net包装器调用此服务的方法(而不是我的http实现),它也会像我的客户端一样有时无法获取完整的XML响应。你熟悉tomcat吗? - hoodoos
你怎么确定问题出在Tomcat上而不是运行在Tomcat上的服务器端应用程序?如果我们应该朝这个方向寻找原因,那么我会检查是否有任何Java(servlet)代码手动使用GzipOutputStream压缩输出,如果有的话,就检查它是否正确地调用了输出流上的close()方法。 - BalusC
其实,真正移除块的是我的代码 :) 奇怪的是我没有尝试过其他的Web服务器,只用了Tomcat!我会进一步寻找区别的。 - hoodoos

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