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

解决Node.js中“Can't set headers after they are sent”中间件报错问题

解决"Can't set headers after they are sent"错误

兄弟,这个报错我太熟了——就是典型的重复发送HTTP响应导致的,咱们先揪出问题根源,再一步步修复:

问题根源分析

你的VerifyToken中间件里有两个关键错误:

  1. 异步操作外的提前next调用:jwt.verify是异步函数,但你在它外面写了return next();,这会在JWT验证完成前就让Express跳到下一个中间件/控制器,导致控制器先发送响应,之后JWT回调又尝试处理,触发重复响应。
  2. 错误处理时的冗余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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:15:03