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

添加return后仍报ERR_HTTP_HEADERS_SENT错误如何解决(React+Express场景)

问题根因

「Cannot set headers after they are sent to the client」错误本质是同一次请求中触发了两次响应发送操作,问题出在authMiddleware.js的protectRoute中间件逻辑:

  • 请求携带合法Bearer token时,try块内验证通过后调用了next()进入getUserProfile路由逻辑返回响应,但代码未终止,会继续执行到中间件末尾的第二个next(),导致重复进入路由逻辑,触发两次响应发送。
  • 同时存在额外功能bug:JWT验证和生成的密钥写法错误,你将密钥写为`{ process.env.JWT_SECRET}`,模板字符串包裹了多余大括号,实际获取的密钥会带大括号,和签名密钥不一致会导致验证一直失败。

修复方案

1. 修正authMiddleware.js逻辑

修改protectRoute函数,验证通过调用next()后加return终止后续代码执行,同时修正密钥写法:

const jwt = require("jsonwebtoken");
const User = require("../models/userModel");
const asyncHandler = require("express-async-handler");

const protectRoute = asyncHandler(async (req, res, next) => {
  let token;
  if (
    req.headers.authorization &&
    req.headers.authorization.startsWith("Bearer")
  ) {
    try {
      token = req.headers.authorization.split(" ")[1];
      // 去掉多余的大括号,正确读取环境变量
      const decoded = jwt.verify(token, process.env.JWT_SECRET);
      console.log(decoded);
      req.user = await User.findById(decoded.id).select("-password");
      // 加return终止代码向下执行
      return next();
    } catch (error) {
      console.error(error);
      return res.status(401).json({ error: "Not authorised. " });
    }
  }

  if (!token) {
    return res.status(401).json({ error: "Not authorised. " });
  }
  next();
});

module.exports = { protectRoute };

2. 修正userController.js中token生成逻辑

修改generateToken函数的密钥写法:

const generateToken = (id) => {
  // 去掉多余的模板字符串包裹和大括号
  return jwt.sign({ id }, process.env.JWT_SECRET, { expiresIn: "30d" });
};

3. 可选优化

给userController.js中的三个异步路由处理函数都用express-async-handler包裹,避免异步代码抛出未捕获异常时可能触发的重复响应问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 09:15:03