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
相关产品推荐
相关产品推荐

