Express中间件开发:响应体超过1MB时返回自定义错误
Express中间件限制响应体大小避免循环问题
你的代码核心问题是:当你在重写的res.end里调用res.end发送错误响应时,会再次触发你自己重写的res.end方法,导致无限循环。另外代码里还有几个需要修正的细节,比如未定义的responseSize、废弃的new BufferAPI。
下面是修复后的完整代码:
function logResponseBody(req, res, next) { const oldWrite = res.write; const oldEnd = res.end; const maxSize = 1024 * 1024; // 1MB,原代码是1023字节,这里修正为你要的1MB let totalSize = 0; const chunks = []; // 重写res.write,累加响应体大小并收集chunk res.write = function(chunk) { const buffer = Buffer.from(chunk); totalSize += buffer.length; chunks.push(buffer); // 如果已经超过大小限制,直接终止后续写入 if (totalSize > maxSize) { return false; } return oldWrite.apply(res, arguments); }; // 重写res.end,检查总大小并处理 res.end = function(chunk) { // 处理最后一段chunk if (chunk) { const buffer = Buffer.from(chunk); totalSize += buffer.length; chunks.push(buffer); } // 先记录响应体日志 const body = Buffer.concat(chunks).toString('utf8'); console.log(req.path, body); // 检查是否超过大小限制 if (totalSize > maxSize) { // 恢复原始的res.write和res.end,避免循环 res.write = oldWrite; res.end = oldEnd; // 发送自定义错误响应 return res.status(314).send('响应体过大,超过1MB限制'); } // 正常结束响应 return oldEnd.apply(res, arguments); }; next(); } app.use(logResponseBody);
关键修复点:
- 避免循环:在发送错误响应前,先把
res.write和res.end恢复为原始方法,这样调用res.status(314).send()时会使用Express原生的响应方法,不会再触发我们重写的逻辑。 - 正确计算大小:直接累加每个chunk的字节长度,比转成字符串后计算长度更高效,也避免大字符串占用过多内存。
- 废弃API替换:用
Buffer.from()替代已废弃的new Buffer(),符合Node.js当前的最佳实践。 - 提前终止写入:在
res.write里就检查大小,一旦超过就返回false,阻止后续的响应内容写入,减少不必要的资源消耗。
内容的提问来源于stack exchange,提问作者Loki
相关产品推荐
相关产品推荐

