如何修复NodeAPI搭配Angular时的ERR_HTTP_HEADERS_SENT错误
问题分析与解决方案
核心问题
- CORS预检请求未正确处理:浏览器发起的OPTIONS预检请求不会携带Authorization头,你的
checkRole函数会因找不到token返回401,导致浏览器拦截后续实际GET请求。同时预检请求要求服务器返回200/204并附带正确CORS头,否则会触发跨域错误。 checkRole函数逻辑漏洞:- 混用
async/await和then/catch,导致代码执行流程混乱 - 当
foundUser不存在时,既未返回响应也未调用next(),会造成请求挂起,进而触发重复发送响应的错误 - 条件判断
foundUser.role != null || foundUser.role != ''逻辑错误,应使用&&(一个值不可能同时为null和空字符串,原判断会导致所有情况都进入分支)
- 混用
修复步骤
1. 正确处理CORS预检请求
在Express应用中添加全局中间件,优先处理OPTIONS请求并返回正确CORS头:
// 放在所有路由之前的全局中间件 app.use((req, res, next) => { // 根据实际需求调整允许的源、方法和请求头 res.setHeader('Access-Control-Allow-Origin', '你的Angular应用域名'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); // 预检OPTIONS请求直接返回204 if (req.method === 'OPTIONS') { return res.sendStatus(204); } next(); });
也可以使用cors包简化配置(推荐):
npm install cors
在应用中引入并配置:
const cors = require('cors'); app.use(cors({ origin: '你的Angular应用域名', allowedHeaders: ['Content-Type', 'Authorization'], methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'] }));
2. 重构checkRole函数逻辑
统一使用async/await,修复条件判断和分支覆盖问题:
const checkRole = async (req, res, next) => { // 若使用cors包,可省略此判断(cors会自动处理OPTIONS请求) if (req.method === 'OPTIONS') { return next(); } try { // 先校验Authorization头是否存在 if (!req.headers.authorization) { return res.sendStatus(401); } const token = req.headers.authorization.split(' ')[1]; const decodedToken = jwt.verify(token, envs.jwtSecret); const foundUser = await User.findById(decodedToken.userId); if (!foundUser) { return res.sendStatus(401); } // 修复条件判断:确保role既非null也非空字符串 if (foundUser.role != null && foundUser.role !== '') { if (foundUser.role.includes('Admin')) { req.userData = { email: decodedToken.email, id: decodedToken.id }; return next(); } } // 所有不满足Admin权限的情况统一返回401 return res.sendStatus(401); } catch (error) { // 捕获token解析、数据库查询等错误,统一返回401 return res.sendStatus(401); } };
3. 验证修复效果
- 启动Node API和Angular应用,查看网络面板:OPTIONS请求将返回204,实际GET请求会正常携带token并通过权限校验
- 控制台不再出现
ERR_HTTP_HEADERS_SENT错误(原错误因分支逻辑不完整导致多次发送响应,修复后分支覆盖完整)
内容的提问来源于stack exchange,提问作者SlappingTheBass12
相关产品推荐
相关产品推荐

