Node.js Express接收application/octet-stream时rawBody长度异常如何修复
问题修复方案
根因分析
- 中间件顺序错误:
express.json()会优先读取并消费请求的数据流,你将它放在自定义采集 rawBody 的中间件之前,导致后者只能拿到未被读取的剩余部分数据,所以出现长度比content-length短的问题。 - 二进制流转码错误:你直接将Buffer类型的请求块拼接为字符串,默认采用UTF-8编码转码。如果客户端发送的是二进制非文本数据,转码过程会出现字节损失、长度计算错误,最终内容和原始数据不符。
修复方案
方案1:调整中间件顺序,自行采集原始请求体
将自定义采集rawBody的中间件放到所有会消费请求流的中间件之前,同时用Buffer存储原始数据,不要提前转字符串:
const express = require('express'); const app = express(); // 优先处理rawBody采集 app.use(function(req, res, next){ const chunks = []; req.on('data', chunk => chunks.push(chunk)) req.on('end', () => { req.rawBody = Buffer.concat(chunks); // 存储原始Buffer,避免转码损失 next(); }) }) // 再配置json解析中间件 app.use(express.json()); app.post('/api/v1/messages', async (clientReq, clientRes) => { const { headers, rawBody } = clientReq; console.log('contentLength:', headers['content-length']) console.log('rawBody.length : ', rawBody.length); // 字节长度和content-length完全一致 // 如需转字符串可调用 rawBody.toString(对应编码格式) clientRes.sendStatus(200); }) app.listen(3000);
方案2:直接使用express内置参数获取rawBody
不需要自行编写流监听逻辑,通过express.json()的verify参数直接获取原始请求Buffer:
const express = require('express'); const app = express(); app.use(express.json({ verify: (req, res, buf) => { req.rawBody = buf; // 直接获取express读取的原始请求Buffer } })); app.post('/api/v1/messages', async (clientReq, clientRes) => { const { headers, rawBody } = clientReq; console.log('contentLength:', headers['content-length']) console.log('rawBody.length : ', rawBody.length); clientRes.sendStatus(200); }) app.listen(3000);
内容的提问来源于stack exchange,提问作者Stefano Della Valle
相关产品推荐
相关产品推荐

