Golang:“压缩/压扁”模块不能解压缩有效的deflate压缩的HTTP主体 [英] Golang: "compress/flate" module can't decompress valid deflate compressed HTTP body

查看:1040
本文介绍了Golang:“压缩/压扁”模块不能解压缩有效的deflate压缩的HTTP主体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题继续讨论开始这里。我发现由于 deflate 压缩了后者,所以HTTP响应正文不能解组到JSON对象中。现在我想知道如何使用Golang进行解压缩。

输入数据



我已将HTTP响应正文转储到'测试'文件中。这是它:

  $ cat test $ b $bx  PAN 0 
; NTJ 。FӮdU|oVRC%FZ ^ HsdW뮑'DHSSFVCr)G,< Z} x_g + 2slr / Oy公司> J3\G9N#[5M ^ v /2Ҕ| H [ 〜7 _崛

让我们确保这个文件可以被解压缩,甚至包含有效的JSON:

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $' timestamp:{tv_sec:1428488670,tv_usec:197041},string_timestamp:2015-04-08 10:24:30.197041,monitor_status:enabled,commands:{REVERSE_LOOKUP :{ 高速缓存:{ 外:{ 成功:0, 失败:0, 大小:0, 时间:0}, 内部:{ 成功:0,故障:0, 大小 :0, 时间 :0}}, 磁盘 :{ 外 :{ 成功 :0, 失败 :0, 大小 :0, 时间: 0}, 内部:{ 成功:13366, 失败:0, 大小:0, 时间:501808}}, 总:{ 存储:{ 成功:0, 失败ures:0},proxy:{successes:13366,failures:0}}},clients:{}}}
$ zlib-flate -uncompress< test | python - m json.tool
{
commands:{
REVERSE_LOOKUP:{
cache:{
....

源代码

  package main 


bytes
compress / flate
fmt
io / ioutil

$ b $ func main(){
fname:=./test
content,err:= ioutil.ReadFile(fname)
if err!= nil {
panic(err)
}
fmt.Println(File content:\\\
,content)

enflated,err:=如果err!= nil {
panic(err)
}
fmt.Println(Enflated: \ n,enflated)
}

错误

  $ go运行uncompress.go 
文件内容t:
[120 156 181 80 65 78 195 48 16 252 10 242 57 69 118 226 166 38 247 156 64 42 42 130 107 100 156 165 88 196 118 149 93 35 160 234 223 89 183 61 112 42 226 192 109 118 118 102 103 180 123 65 62 0 146 13 59 209 237 5 189 15 8 78 116 74 215 70 27 211 174 100 85 184 124 34 111 86 82 171 67 37 144 102 31 183 195 15 167 168 165 90 46 164 94 72 115 165 100 87 235 174 145 215 39 189 168 68 72 209 83 154 7 22 83 70 86 67 180 207 19 140 188 114 41 4 27 71 44 225 155 254 169 223 60 244 195 221 122 125 251 120 95 24 103 221 43 20 144 50 161 31 143 16 179 115 128 8 108 225 114 47 214 79 121 62 15 232 191 224 8 74 51 6 92 213 71 130 57 218 233 175 78 182 142 30 223 254 35 91 53 77 219 94 118 47 165 50 210 148 18 148 232 124 128 31 104 183 151 91 176 126 55 167 143 207 95 3 15 229 180 155 60 68 42 159 231 241 27 47 165 167 25]
恐慌:flate:腐败输入前补偿5

goroutine 1 [running]:
runtime.panic(0x4a7180,0x5)
/usr/lib/go/src/pkg/runtime/panic.c :266 + 0xb6
main.main()
/home/isaev/side-projects/elliptics-manager/uncompress.go:20 + 0x2a3
退出状态2

$ b

PS Ubuntu 14.10,Go 1.2.1

解决方案

您的输入不是一个简单的缩小块,它是一个 zlib流

根据<一个href =http://tools.ietf.org/html/rfc1950 =nofollow> ZLIB压缩数据格式规范3.3 前两个字节为:

  ------------- 
| CMF | FLG |
-------------

压缩方法和标志。你的输入以 [120,156] 开始,它是 78 9C 这是默认压缩。也没有字典,所以后面的数据是压缩数据。

位0到3是CM压缩方法,位4到7是CINFO压缩信息。在这种情况下,CINFO = 7表示32K窗口大小,CM = 8表示放气压缩方法。 FLG位5告诉字典是否被预置,在这种情况下。 FLG的详细信息也位于链接的 RFC 1950 中。



所以你的输入基本上告诉其余的数据是使用默认压缩构造的,但是去 flate 包不会对此进行解码。 / p>

更改解压缩以省略这样的前2个字节,它将起作用:

  enflated,err:= ioutil.ReadAll(flate.NewReader(bytes.NewReader(content [2:])))

请在去游乐场试试。但是...



使用正确的ZLib解压缩!

因为压缩级别是默认的,字典是预设的。如果没有,您将无法使用 flate 包对其进行解码。由于输入是zlib流,因此您应该使用 compress / zlib

  r,err:= zlib。c $ c> 包可以正确解码并且不依赖于运气: NewReader(bytes.NewReader(content))
if err!= nil {
panic(err)
}
enflated,err:= ioutil.ReadAll(r)
如果err!= nil {
panic(err)
}
fmt.Println(string(enflated))

尝试 _Srel =nofollow>去游乐场


This question continues the discussion started here. I found out that the HTTP response body can't be unmarshaled into JSON object because of deflate compression of the latter. Now I wonder how can I perform decompression with Golang. I will appreciate anyone who can show the errors in my code.

Input data

I've dumped the HTTP response body into the 'test' file. Here is it:

$ cat test
x��PAN�0�
;��NtJ�FӮdU�|"oVR�C%�f�����Z.�^Hs�dW뮑�'��DH�S�SFVC����r)G,�����<���z}�x_g�+�2��sl�r/�Oy>��J3\�G�9���N���#[5M�^v/�2Ҕ��|�h��[�~7�_崛<D*���/��i

Let's make sure that this file can be decompressed and even contains valid JSON:

$ zlib-flate -uncompress < test
{"timestamp":{"tv_sec":1428488670,"tv_usec":197041},"string_timestamp":"2015-04-08 10:24:30.197041","monitor_status":"enabled","commands":{"REVERSE_LOOKUP":{"cache":{"outside":{"successes":0,"failures":0,"size":0,"time":0},"internal":{"successes":0,"failures":0,"size":0,"time":0}},"disk":{"outside":{"successes":0,"failures":0,"size":0,"time":0},"internal":{"successes":13366,"failures":0,"size":0,"time":501808}},"total":{"storage":{"successes":0,"failures":0},"proxy":{"successes":13366,"failures":0}}},"clients":{}}}
$ zlib-flate -uncompress < test | python -m json.tool
{
    "commands": {
        "REVERSE_LOOKUP": {
            "cache": {
               ....

Source code

package main

import (
    "bytes"
    "compress/flate"
    "fmt"
    "io/ioutil"
)

func main() {
    fname := "./test"
    content, err := ioutil.ReadFile(fname)
    if err != nil {
        panic(err)
    }
    fmt.Println("File content:\n", content)

    enflated, err := ioutil.ReadAll(flate.NewReader(bytes.NewReader(content)))
    if err != nil {
        panic(err)
    }
    fmt.Println("Enflated:\n", enflated)
}

Error

$ go run uncompress.go 
File content:
 [120 156 181 80 65 78 195 48 16 252 10 242 57 69 118 226 166 38 247 156 64 42 42 130 107 100 156 165 88 196 118 149 93 35 160 234 223 89 183 61 112 42 226 192 109 118 118 102 103 180 123 65 62 0 146 13 59 209 237 5 189 15 8 78 116 74 215 70 27 211 174 100 85 184 124 34 111 86 82 171 67 37 144 102 31 183 195 15 167 168 165 90 46 164 94 72 115 165 100 87 235 174 145 215 39 189 168 68 72 209 83 154 7 22 83 70 86 67 180 207 19 140 188 114 41 4 27 71 44 225 155 254 169 223 60 244 195 221 122 125 251 120 95 24 103 221 43 20 144 50 161 31 143 16 179 115 128 8 108 225 114 47 214 79 121 62 15 232 191 224 8 74 51 6 92 213 71 130 57 218 233 175 78 182 142 30 223 254 35 91 53 77 219 94 118 47 165 50 210 148 18 148 232 124 128 31 104 183 151 91 176 126 55 167 143 207 95 3 15 229 180 155 60 68 42 159 231 241 27 47 165 167 25]
panic: flate: corrupt input before offset 5

goroutine 1 [running]:
runtime.panic(0x4a7180, 0x5)
    /usr/lib/go/src/pkg/runtime/panic.c:266 +0xb6
main.main()
    /home/isaev/side-projects/elliptics-manager/uncompress.go:20 +0x2a3
exit status 2

PS Ubuntu 14.10, Go 1.2.1

解决方案

Your input is not a simple deflated block, it's a zlib stream.

According to the ZLIB Compressed Data Format Specification 3.3 the first 2 bytes are:

-------------
| CMF | FLG |
-------------

The Compression Method and flags. Your input starts with [120, 156] which is 78 9C in hexa. This is the Default Compression. Also no dictionary follows, so the subsequent data is the compressed data.

Bits 0 to 3 are CM Compression Method and bits 4 to 7 are CINFO Compression Info. In this case CINFO=7 indicates a 32K window size, CM=8 denotes the "deflate" compression method. FLG bit 5 tells if a dictionary is preset, which is in this case. Details of the FLG are also in the linked RFC 1950.

So your input basically tells the rest of the data was constructed using default compression, but the go flate package does not decode this.

Change your decompression to omit the first 2 bytes like this and it will work:

enflated, err := ioutil.ReadAll(flate.NewReader(bytes.NewReader(content[2:])))

Try it on the Go Playground. But...

Use Proper ZLib decompression!

We got lucky this time because the compression level is the default and dictionary was preset. If not, you won't be able to decode it using the flate package. Since the input is a zlib stream, you should use the compress/zlib package to properly decode it and not rely on luck:

r, err := zlib.NewReader(bytes.NewReader(content))
if err != nil {
    panic(err)
}
enflated, err := ioutil.ReadAll(r)
if err != nil {
    panic(err)
}
fmt.Println(string(enflated))

Try the zlib variant on the Go Playground.

这篇关于Golang:“压缩/压扁”模块不能解压缩有效的deflate压缩的HTTP主体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆