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

Express使用JSON解析器时出现[ERR_STREAM_WRITE_AFTER_END]错误排查

解决Express中[ERR_STREAM_WRITE_AFTER_END]: write after end错误

你遇到的这个错误核心原因很明确:你在全局中间件里强行调用了res.end(),而路由处理逻辑中(或隐式的中间件操作中)已经完成了响应流的结束操作,重复调用res.end()就会触发Node.js的流操作错误。

咱们拆解一下你的代码流程,就能明白问题出在哪:
当你发送application/json请求时,请求会先进入全局中间件,执行到await next()后,会依次经过jsonParser中间件(解析请求体)、路由处理函数。路由里调用了res.write('ok')写入响应数据,但没有显式结束响应;等路由处理完成回到全局中间件时,你又调用了res.end()——这看似没问题,但结合jsonParser的行为,内部可能已经触发了响应流的状态变化,导致第二次调用res.end()时,Node.js检测到响应流已经被标记为结束,从而抛出错误。而当你不用jsonParser时,请求体没有被解析,响应流的状态没有被触发变化,所以重复调用res.end()暂时没报错,但这其实也是不安全的写法。

你不需要放弃全局中间件,只需要调整写法就能满足需求

你的核心需求是用全局中间件做请求前后的统一处理,这完全可以实现,只要避免在中间件里手动结束响应即可:

方案1:使用Express高层响应方法(推荐)

Express提供的res.send()、res.json()等方法会自动帮你设置响应头、写入数据并结束响应,不需要手动调用res.end()。修改你的代码如下:

import express from 'express';
const app = express();
const jsonParser = express.json();

// 全局中间件:只做前后置处理,不手动结束响应
app.use(async (req, res, next) => {
  // 前置操作:统一设置响应头、打印日志
  console.log('Raw request:', req.method, req.path);
  res.setHeader('Content-Type', 'application/json');
  await next();
  // 后置操作:比如打印响应完成日志
  console.log('Response finished for:', req.path);
});

app.post('/example', jsonParser, async (req, res) => {
  console.log('Parsed request body:', req.body);
  // 使用res.json返回合法JSON,自动结束响应
  res.json({ message: 'ok' });
});

app.listen(3000);

方案2:如果必须使用底层的res.write()

如果你确实需要分块写入响应(比如流式返回数据),那应该在路由处理函数中自己调用res.end(),不要依赖中间件:

import express from 'express';
const app = express();
const jsonParser = express.json();

app.use(async (req, res, next) => {
  console.log('Raw request:', req.method, req.path);
  res.setHeader('Content-Type', 'application/json');
  await next();
  console.log('Response finished for:', req.path);
});

app.post('/example', jsonParser, async (req, res) => {
  console.log('Parsed request body:', req.body);
  // 分块写入数据后,手动结束响应
  res.write('{"message": "ok"}');
  res.end();
});

app.listen(3000);

额外提示

你之前设置了Content-Type: application/json,但路由里返回的是字符串ok,这不符合JSON格式规范,会导致客户端解析失败。用res.json()可以自动帮你把数据序列化为合法的JSON,同时保持响应头的一致性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:14:28