如何保持 HTTP 的 gzip 表示 body

How to keep the gzip representation of HTTP body

在 go web 应用程序的上下文中,我使用响应缓存并压缩它们,因此我节省了带宽(响应更大)。我正在使用 gin-gonic 框架和包 gzip 进行压缩。这个包工作得很好,可以满足我接收和回复 gzip-compressed 正文所需的一切。这两行就足够了:

router := gin.Default()
router.Use(gzip.Gzip(gzip.DefaultCompression))

一切都是神奇的。现在,我还使用了一个存储响应的缓存。为了保存 space 和 CPU,我想将已经压缩的响应存储在缓存中,所以我也不会重复压缩。作为包装 HTTP body 处理的中间件,gzip 透明地解压缩请求并压缩响应。但是,在我的处理程序级别,我想获得我的响应的压缩表示,以便我可以将其存储到我的缓存中。另外,我需要告诉 gzip 我的 body 已经压缩了。

我已经搜索了一些使用 gzip 包或任何其他包的自动化方式,这阻止了我干预某些库、HTTP 堆栈中的执行路径,或者更糟糕的是,我自己编写一些东西已经由另一个库制作,例如 gzip.

有人body知道gzip包如何解决这个问题吗?

首先,我继续使用 gzipgin 软件包。

现在,我用类似这样的函数压缩我的回复:

func compress(response interface{}) ([]byte, error) {
    body, err := json.Marshal(response)
    if err != nil {
        return nil, err
    }
    var buffer bytes.Buffer
    zw := gzip.NewWriter(&buffer)
    _, err = zw.Write(body)
    closeErr := zw.Close()
    if err != nil {
        return nil, err
    }
    if closeErr != nil {
        return nil, err
    }
    return buffer.Bytes(), nil
}

当我需要响应请求时,我会执行这样的操作:

    gzipOutput, err := compressResponse(output)
    if err != nil {
        c.JSON(http.StatusInternalServerError, err.Error())
        return
    }

    c.Writer.Header().Set("Accept-Encoding", "gzip")
    c.Writer.Header().Set("Content-Encoding", "gzip")
    c.Writer.Header().Set("Content-Type", "application/json")
    c.Data(http.StatusOK, "gzip", gzipOutput)

正如我们所见,这个想法是告诉 gin 通过设置 HTML header.

来压缩响应

八个月以来,它已经在五个不同的 API 上进行了测试。

我希望它对其他人有用,就像对我一样。