You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gin框架处理gzip压缩请求遇gzip: invalid header错误,求修正方案

错误原因及修正方案

错误原因

  1. 前端压缩格式不匹配:pako库的deflate()和gzip()是两种不同的压缩实现。如果前端使用pako.deflate()生成压缩数据,输出的是raw deflate格式(无gzip标准的头部/尾部标识),但后端用gzip.NewReader()读取时要求标准gzip格式,因此触发gzip: invalid header错误。
  2. gin中间件误解:你添加的gzip.Gzip(gzip.DefaultCompression)中间件仅用于压缩响应数据,不会处理请求体的解压,和当前错误无关,但需注意不要混淆其作用。

修正方法

方案一:前端改用标准gzip压缩(推荐)

确保前端使用pako的gzip()方法生成符合标准的gzip格式数据,同时设置正确的请求头:

// Angular前端示例代码
import * as pako from 'pako';

// 构造并压缩JSON数据
const payload = { foo: "bar" };
const rawData = new TextEncoder().encode(JSON.stringify(payload));
const compressedData = pako.gzip(rawData);

// 发送请求时设置头部
const requestHeaders = new HttpHeaders()
  .set('Content-Encoding', 'gzip')
  .set('Content-Type', 'application/json');

this.http.post('/test', compressedData, { headers: requestHeaders }).subscribe(
  res => console.log(res),
  err => console.error(err)
);

方案二:后端适配deflate格式(若前端无法修改)

如果前端确实使用deflate压缩,后端需替换gzip.NewReader()为flate.NewReader(),同时修改请求头判断:

import (
  "bytes"
  "compress/flate"
  "io/ioutil"
  "net/http"
  "fmt"

  "github.com/gin-gonic/gin"
)

func Test(c *gin.Context) {
  if c.GetHeader("Content-Encoding") == "deflate" {
    // 读取压缩请求体
    compressedBody, err := ioutil.ReadAll(c.Request.Body)
    if err != nil {
      c.String(http.StatusBadRequest, "Failed to read request body")
      return
    }
    defer c.Request.Body.Close()

    // 使用flate reader解压
    reader := flate.NewReader(bytes.NewReader(compressedBody))
    defer reader.Close()

    uncompressedBody, err := ioutil.ReadAll(reader)
    if err != nil {
      c.String(http.StatusInternalServerError, "Failed to decompress body")
      return
    }

    fmt.Println("Decompressed data:", string(uncompressedBody))
    c.String(http.StatusOK, "Received and decompressed data successfully")
  } else {
    c.String(http.StatusBadRequest, "Expected deflated data in request")
  }
}

进阶优化:使用全局解压中间件

避免在每个Handler中重复编写解压逻辑,可以自定义全局中间件自动处理请求解压:

import (
  "compress/gzip"
  "compress/flate"
  "io/ioutil"
  "net/http"

  "github.com/gin-gonic/gin"
)

// 自动解压请求体的中间件
func RequestDecompressMiddleware() gin.HandlerFunc {
  return func(c *gin.Context) {
    encoding := c.GetHeader("Content-Encoding")
    switch encoding {
    case "gzip":
      reader, err := gzip.NewReader(c.Request.Body)
      if err != nil {
        c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid gzip data"})
        return
      }
      defer reader.Close()
      c.Request.Body = ioutil.NopCloser(reader)
    case "deflate":
      reader := flate.NewReader(c.Request.Body)
      defer reader.Close()
      c.Request.Body = ioutil.NopCloser(reader)
    }
    c.Next()
  }
}

// 路由注册时添加中间件
func main() {
  router := gin.Default()
  router.Use(RequestDecompressMiddleware()) // 先处理请求解压
  router.Use(gzip.Gzip(gzip.DefaultCompression)) // 再处理响应压缩

  router.POST("/test", Test)
  router.Run(":8080")
}

// 此时Test函数可直接读取已解压的请求体
func Test(c *gin.Context) {
  body, err := ioutil.ReadAll(c.Request.Body)
  if err != nil {
    c.String(http.StatusBadRequest, "Failed to read request body")
    return
  }
  fmt.Println("Received data:", string(body))
  c.String(http.StatusOK, "Received data successfully")
}

内容的提问来源于stack exchange,提问作者Rohit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 06:11:17