添加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
相关产品推荐
相关产品推荐

