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

serverless-http下gunzip解压gzip请求报incorrect header check错误

问题原因

报错Z_DATA_ERROR: incorrect header check的核心原因是Lambda + API Gateway的请求处理逻辑和原生Node.js HTTP服务存在差异,和zlib解压逻辑本身无关:

  • 原生Express服务直接从HTTP套接字读取原始二进制请求流,拿到的Buffer是完整的gzip格式数据,所以解压正常
  • serverless-http默认不会对二进制类型请求做特殊处理,API Gateway会将application/gzip这类二进制内容做base64编码后再传给Lambda,你代码里拼接拿到的Buffer实际是base64字符串的二进制表示,不是真实的gzip文件内容,自然会报头校验错误。
    另外你代码里手动给gunzip加的finishFlush: zlib.constants.Z_SYNC_FLUSH参数是多余的,标准gzip压缩文件不需要这个配置,反而可能引发解压异常。
修复方案

按以下两步调整即可:

1. 修改serverless-http初始化配置,正确处理二进制请求

初始化serverless-http时明确指定需要处理的二进制媒体类型,同时增加base64编码兜底判断,修复后的完整代码如下:

const serverless = require("serverless-http");
const express = require("express");
const { unzip } = require("node:zlib");
const { promisify } = require("node:util");
const compression = require("compression");

const app = express();
// 限制json中间件只处理json类型请求,避免提前消费gzip请求流
app.use(express.json({ type: ["application/json"] }));
app.use(compression());

const do_unzip = promisify(unzip);

app.post("/unzip", async (req, res, next) => {
  const isAccepted = req.headers["content-type"] === "application/gzip";
  if (!isAccepted) return res.status(406).json({ message: "Not Acceptable" });

  const chunks = [];
  req.on("data", (chunk) => chunks.push(chunk));
  req.on("end", async () => {
    try {
      let buff = Buffer.concat(chunks);
      // 兜底判断:如果请求是API Gateway传的base64编码内容,先解码为原始二进制
      if (req.apiGateway && req.apiGateway.event.isBase64Encoded) {
        buff = Buffer.from(buff.toString("utf8"), "base64");
      }
      const decompressedRes = await do_unzip(buff);
      return res.status(200).json({
        result: decompressedRes.toString()
      });
    } catch (error) {
      next(error);
    }
  });
});

app.use((err, req, res, next) => {
  console.error(err);
  return res.status(500).json({
    error: {
      errno: err.errno,
      code: err.code
    },
    message: err.message
  });
});

// 关键配置:声明gzip为二进制类型,让serverless-http正确处理
module.exports.handler = serverless(app, {
  binary: ["application/gzip"]
});

2. 调整云服务侧配置

如果你用API Gateway触发Lambda,需要在服务配置里把application/gzip加入二进制媒体类型列表,以Serverless Framework配置为例,在serverless.yml中添加如下配置:

provider:
  name: aws
  runtime: nodejs18.x # 按需调整你的Node.js版本
  apiGateway:
    binaryMediaTypes:
      - "application/gzip"

如果你用Lambda Function URL触发,直接在Function URL的配置页把application/gzip加入二进制媒体类型列表即可。

验证要点
  • 不要混用unzip和gunzip,优先用unzip方法,它会自动识别gzip/deflate压缩头,兼容性更好
  • 去掉多余的finishFlush配置,标准gzip压缩包不需要额外指定flush参数
  • 本地测试可以用serverless-offline插件,同样需要在offline配置里开启二进制媒体类型支持,否则本地模拟也会复现同类错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 11:18:16