为了账号安全,请及时绑定邮箱和手机立即绑定

Golang:“压缩/扁平化”模块无法解压缩有效的 deflate 压缩 HTTP 正文

Golang:“压缩/扁平化”模块无法解压缩有效的 deflate 压缩 HTTP 正文

Go
梵蒂冈之花 2021-09-27 17:45:02
这个问题延续了这里开始的讨论。我发现 HTTP 响应正文由于deflate后者的压缩而无法解组为 JSON 对象。现在我想知道如何使用 Golang 进行解压。我将感谢任何可以在我的代码中显示错误的人。输入数据我已将 HTTP 响应正文转储到“测试”文件中。就这个:$ cat testx��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让我们确保这个文件可以解压缩,甚至包含有效的 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": {               ....源代码package mainimport (    "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)}错误$ go run uncompress.go panic: flate: corrupt input before offset 5goroutine 1 [running]:runtime.panic(0x4a7180, 0x5)    /usr/lib/go/src/pkg/runtime/panic.c:266 +0xb6main.main()    /home/isaev/side-projects/elliptics-manager/uncompress.go:20 +0x2a3exit status 2PS Ubuntu 14.10,转到 1.2.1
查看完整描述

1 回答

?
慕斯709654

TA贡献1840条经验 获得超5个赞

您的输入不是一个简单的压缩块,而是一个zlib 流。


根据ZLIB 压缩数据格式规范 3.3,前 2 个字节是:


-------------

| CMF | FLG |

-------------

压缩方法和标志。您的输入以十六进制的[120, 156]which开头78 9C。这是默认压缩。也没有字典跟随,所以后续数据是压缩数据。


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


所以你的输入基本上告诉其余的数据是使用默认压缩构造的,但是 goflate包不会解码它。


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


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

在Go Playground上试一试。但...


使用正确的 ZLib 解压!


这次我们很幸运,因为压缩级别是默认的,并且字典是预设的。如果没有,您将无法使用该flate包对其进行解码。由于输入是 zlib 流,因此您应该使用该compress/zlib包对其进行正确解码,而不要依赖运气:


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))

zlib在Go Playground上试试这个变体。


查看完整回答
反对 回复 2021-09-27
  • 1 回答
  • 0 关注
  • 576 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信