解决Node.js中“Can't set headers after they are sent”中间件报错问题
解决"Can't set headers after they are sent"错误
兄弟,这个报错我太熟了——就是典型的重复发送HTTP响应导致的,咱们先揪出问题根源,再一步步修复:
问题根源分析
你的VerifyToken中间件里有两个关键错误:
- 异步操作外的提前next调用:
jwt.verify是异步函数,但你在它外面写了return next();,这会在JWT验证完成前就让Express跳到下一个中间件/控制器,导致控制器先发送响应,之后JWT回调又尝试处理,触发重复响应。 - 错误处理时的冗余next调用:
res.json()和res.sendStatus()本身就会结束请求响应周期,你却把它们作为参数传给next(),这会让Express继续处理后续逻辑,再次尝试发送响应。
修复后的代码
1. 修正VerifyToken.js中间件
module.exports = (req, res, next) => { var token = req.headers['authorization']; // Check if token used is undefined if(typeof token !== 'undefined') { jwt.verify(token, 'secretkey', (err, authData) => { if(err) { // 直接发送错误响应,无需调用next return res.json({ message : 'You are not authorized to be here'}); } else { var usertoken = { id : authData.user._id, username : authData.user.username }; res.locals.usertoken = usertoken; // 验证通过,跳转到下一个处理逻辑 return next(); } }); // 删掉这里的return next()!异步操作必须等回调完成再处理 } else { // 直接发送403状态,无需调用next return res.sendStatus(403); } }
2. 控制器代码保持不变(users.js)
module.exports.me_get = (req, res, next) => { return res.json({ message : 'You have arrived!', usertoken : res.locals.usertoken }); }
3. 路由代码保持不变(user.js)
router.get('/me', VerifyToken, userController.me_get);
修复逻辑说明
- 当token不存在时,直接发送
403 Forbidden响应,请求到此结束。 - 当token无效时,直接发送错误JSON响应,请求到此结束。
- 当token有效时,设置
res.locals.usertoken后调用next(),让控制器处理并发送最终响应,整个请求周期只会发送一次响应。
这样修改后,控制台的"Can't set headers after they are sent"错误就会消失啦!
内容的提问来源于stack exchange,提问作者doobiz
相关产品推荐
相关产品推荐

