Express登录验证测试时服务崩溃报Cannot set headers错误如何解决
问题原因分析
你遇到的两个报错是因果关系:
Cannot set headers after they are sent to the client:Express 规则限制同一次请求只能发送一次响应,只要调用过res.json/res.send等返回方法,就不能再修改响应头、再次发送响应,重复调用就会抛出这个错误,直接导致 Node 服务进程崩溃ERR_CONNECTION_REFUSED:服务进程崩溃后停止监听端口,后续请求无法建立连接就会返回这个错误
代码BUG定位
所有问题都出在服务端路由逻辑的流程控制缺失:
1. 登录接口核心BUG
router.post("/login", async (req, res) => { const { username, password } = req.body; const user = await Users.findOne({ where: { username: username } }); // 问题1:用户不存在时返回响应后,代码没有中断,会继续执行后续逻辑 if (!user) res.json("User Doesn't exist"); bcrypt.compare(password, user.password).then((match) => { // 问题2:密码不匹配时返回响应后,代码没有中断,会继续执行下一行的res.json,导致同一次请求返回两次响应 if (!match) res.json("Wrong Username or Password"); res.json("YOU LOGGED IN"); }); });
当测试用户名不存在、密码错误场景时,就会触发两次res.json调用,直接触发报错。
2. 注册接口潜在问题
bcrypt.hash(password, 10).then((hash) => { // Users.create是异步操作,没有等待完成就返回响应,入库失败时前端会收到成功提示,逻辑不符 Users.create({ username: username, password: hash, phone: phone, email: email, }); res.json("SUCCESS"); });
同时没有异步操作的错误捕获逻辑,任意数据库、bcrypt操作报错都会导致服务崩溃。
修复后的服务端代码
统一用async/await优化异步逻辑,添加return中断代码执行,保证同一次请求仅返回一次响应,补充错误捕获:
const express = require("express"); const router = express.Router(); const { Users } = require("../models"); const bcrypt = require('bcryptjs'); // 注册接口修复 router.post("/", async (req, res) => { try { const {username, password, phone, email} = req.body; const user = await Users.findOne({ where: {username: username}}); if(user) { return res.json({ error: "User is unavailable"}); } const hash = await bcrypt.hash(password, 10); await Users.create({ username: username, password: hash, phone: phone, email: email, }); return res.json("SUCCESS"); } catch (err) { return res.status(500).json({error: "服务内部错误"}); } }); // 登录接口修复 router.post("/login", async (req, res) => { try { const { username, password } = req.body; const user = await Users.findOne({ where: { username: username } }); if (!user) { return res.json("User Doesn't exist"); } const match = await bcrypt.compare(password, user.password); if (!match) { return res.json("Wrong Username or Password"); } return res.json("YOU LOGGED IN"); } catch (err) { return res.status(500).json({error: "服务内部错误"}); } }); module.exports = router;
内容的提问来源于stack exchange,提问作者Tim Nguyen
相关产品推荐
相关产品推荐

