如何解码python中HTTP响应中返回的gzip压缩数据?

时间:2012-03-18 20:30:09

标签: python http sockets zlib

我在python中创建了一个客户端/服务器体系结构,我从客户端获取HTTP请求,该请求通过我的代码请求另一个HTTP服务器来提供服务。

当我从第三台服务器得到响应时,我无法解码gzip压缩数据,我首先使用\r\n将响应数据拆分为分离字符,这使得数据成为列表中的最后一项然后我尝试用

解压缩它
zlib.decompress(data[-1]) 

但它给我一个错误的标题错误。我该如何解决这个问题?

代码

client_reply = ''
                 while 1:
                     chunk = server2.recv(512)
                     if len(chunk) :
                         client.send(chunk)
                         client_reply += chunk
                     else:
                         break
                 client_split = client_reply.split("\r\n")
                 print client_split[-1].decode('zlib')

我想读取客户端和第二台服务器之间传输的数据。

2 个答案:

答案 0 :(得分:5)

使用int idCreate = 0; List<int> idSaved = new List<int>(); protected override async void OnLaunched(LaunchActivatedEventArgs e) { Frame rootFrame = Window.Current.Content as Frame; if (rootFrame == null) { rootFrame = new Frame(); rootFrame.NavigationFailed += OnNavigationFailed; Window.Current.Content = rootFrame; } if (rootFrame.Content == null) { rootFrame.Navigate(typeof(MainPage), e.Arguments); idSaved.Add(ApplicationView.GetForCurrentView().Id); } else { var create = CoreApplication.CreateNewView(); await create.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { var frame = new Frame(); frame.Navigate(typeof(MainPage), e.Arguments); Window.Current.Content = frame; Window.Current.Activate(); idCreate = ApplicationView.GetForCurrentView().Id; }); for(int i = idSaved.Count - 1; i >= 0; i--) if (await ApplicationViewSwitcher.TryShowAsStandaloneAsync( idCreate, ViewSizePreference.UseMinimum, idSaved[i], ViewSizePreference.UseMinimum) ) break; idSaved.Add(idCreate); } Window.Current.Activate(); } 时指定wbits,请参阅&#34;故障排除&#34;例如。

故障排除

让我们从一个curl命令开始,该命令下载一个带有未知&#34;内容编码&#34;的字节范围响应。 (注意:我们事先知道它是某种压缩的东西,mabye zlib.decompress(string, wbits, bufsize)也许deflate):

gzip

使用以下响应标头:

export URL="https://commoncrawl.s3.amazonaws.com/crawl-data/CC-MAIN-2016-18/segments/1461860106452.21/warc/CC-MAIN-20160428161506-00007-ip-10-239-7-51.ec2.internal.warc.gz"
curl -r 266472196-266527075 $URL | gzip -dc | tee hello.txt

所以说到这一点。

让我们显示前10个字节的十六进制输出: HTTP/1.1 206 Partial Content x-amz-id-2: IzdPq3DAPfitkgdXhEwzBSwkxwJRx9ICtfxnnruPCLSMvueRA8j7a05hKr++Na6s x-amz-request-id: 14B89CED698E0954 Date: Sat, 06 Aug 2016 01:26:03 GMT Last-Modified: Sat, 07 May 2016 08:39:18 GMT ETag: "144a93586a13abf27cb9b82b10a87787" Accept-Ranges: bytes Content-Range: bytes 266472196-266527075/711047506 Content-Type: application/octet-stream Content-Length: 54880 Server: AmazonS3

十六进制输出:

curl -r 266472196-266472208 $URL | xxd

我们可以看到我们使用十六进制值的一些基础知识。

粗略地说它可能是一个gzip(0000000: 1f8b 0800 0000 0000 0000 ecbd eb )使用deflate(1f8b)而没有修改时间(0800),或任何额外的标志设置(0000 0000),使用fat32系统(00)。

请参阅第2.3 / 2.3.1节:https://tools.ietf.org/html/rfc1952#section-2.3.1

所以进入python:

00

注意到类似的东西?:

>>> import requests
>>> url = 'https://commoncrawl.s3.amazonaws.com/crawl-data/CC-MAIN-2016-18/segments/1461860106452.21/warc/CC-MAIN-20160428161506-00006-ip-10-239-7-51.ec2.internal.warc.gz'
>>> response = requests.get(url, params={"range":"bytes=257173173-257248267"})
>>> unknown_compressed_data = response.content

对于解压缩,我们只需根据(documentation)随机尝试:

>>> unknown_compressed_data[:10]
'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00'

&#34; zlib.error:准备解压缩数据时错误-2:不一致的流状态&#34;

>>> import zlib

&#34;解压缩数据时出错-3:错误的标题检查&#34;:

>>> zlib.decompress(unknown_compressed_data, -31)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
zlib.error: Error -2 while preparing to decompress data: inconsistent stream state

&#34; zlib.error:解压缩数据时出错-3:无效距离太远&#34;

>>> zlib.decompress(unknown_compressed_data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
zlib.error: Error -3 while decompressing data: incorrect header check

可能的解决方案:

>>> zlib.decompress(unknown_compressed_data, 30)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
zlib.error: Error -3 while decompressing data: invalid distance too far back

答案 1 :(得分:1)

根据https://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html,标题和正文由仅包含CRLF字符的空行分隔。你可以试试

client_split = client_reply.split("\r\n\r\n",1)
print client_split[1].decode('zlib')

拆分找到空行,附加参数限制拆分数 - 结果是包含两个项目的数组,标题和正文。但是如果不了解更多关于代码和实际字符串被拆分的话,很难推荐任何东西。