Express认证时崩溃:ERR_HTTP_HEADERS_SENT错误排查
问题原因与解决方法
这个错误Error [ERR_HTTP_HEADERS_SENT]的核心是:你在已经给客户端发送了一次响应后,代码还继续执行,又尝试发送第二次响应。
看你的代码逻辑:
- 当用户名不存在(
!user)时,你发送了res.status(400).json("Wrong credentials."),但这行代码之后没有终止函数执行,程序会继续往下走,执行bcrypt.compare(这里还会因为user是undefined报错,被catch捕获后又会发送一次500的响应); - 同理,密码验证不通过时发送了400响应,但之后还是会执行最后的
res.status(200).json(user),导致重复发送响应。
修复代码的两种方式:
方式一:用return终止函数执行
在发送错误响应后加上return,确保后续代码不再执行:
router.post("/login", async (req, res) => { try { const user = await User.findOne({ username: req.body.username }); if (!user) { return res.status(400).json("Wrong credentials."); } const validated = await bcrypt.compare(req.body.password, user.password); if (!validated) { return res.status(400).json("Wrong credentials."); } res.status(200).json(user); } catch(err) { res.status(500).json(err); } });
这里把原来的&&改成if语句并加上return,逻辑更清晰,也能避免后续代码继续执行。
方式二:用if-else结构控制流程
router.post("/login", async (req, res) => { try { const user = await User.findOne({ username: req.body.username }); if (!user) { res.status(400).json("Wrong credentials."); } else { const validated = await bcrypt.compare(req.body.password, user.password); if (!validated) { res.status(400).json("Wrong credentials."); } else { res.status(200).json(user); } } } catch(err) { res.status(500).json(err); } });
这种方式通过分支判断,确保每次只会执行一个响应发送逻辑,不会出现重复发送的情况。
总结:Node.js的res对象只能发送一次响应,一旦调用了res.json()、res.send()这类方法,后续再调用就会触发这个错误,所以必须确保发送响应后终止当前函数的执行,或者用分支逻辑避免进入后续的响应发送代码。
内容的提问来源于stack exchange,提问作者ChronoKross
相关产品推荐
相关产品推荐

