调用登录API时出现ERR_HTTP_HEADERS_SENT错误求助
MERN项目登录接口报错:Error [ERR_HTTP_HEADERS_SENT]
我正在制作首个MERN项目,登录前可正常从MongoDB获取数据,但提交登录表单时触发错误:Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client。已搜索4小时仍未找到重复发送响应头的原因,以下是相关代码及错误栈信息,恳请帮助排查问题。
错误栈信息
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at new NodeError (node:internal/errors:372:5) at ServerResponse.setHeader (node:_http_outgoing:576:11) at ServerResponse.header (E:\Blog-Website\api\node_modules\express\lib\response.js:794:10) at ServerResponse.send (E:\Blog-Website\api\node_modules\express\lib\response.js:174:12) at ServerResponse.json (E:\Blog-Website\api\node_modules\express\lib\response.js:278:15) at E:\Blog-Website\api\routes\auth.js:37:23 at processTicksAndRejections (node:internal/process/task_queues:96:5) { code: 'ERR_HTTP_HEADERS_SENT'
后端auth.js代码
const router = require("express").Router(); const User = require("../models/User"); const bcrypt = require('bcrypt'); //REGISTER router.post("/register", async (req, res) => { try { const salt = await bcrypt.genSalt(10); const hashedPass = await bcrypt.hash(req.body.password, salt); const newUser = new User({ username: req.body.username, email: req.body.email, password: hashedPass, }); const user = await newUser.save(); console.log(user) res.status(200).json(user); } catch (err) { res.status(500).json(err); } }); //LOGIN router.post("/login", async (req, res) => { try { const user = await User.findOne({ username: req.body.username }); !user && res.status(400).json("Wrong credentials!"); const validated = await bcrypt.compare(req.body.password, user.password); !validated && res.status(400).json("Wrong credentials!"); const { password, ...others } = user._doc; res.status(200).json(others); } catch (err) { res.status(500).json(err); } }); module.exports = router
前端login.jsx代码
import { Link } from "react-router-dom"; import "./login.css" import { useContext, useRef } from "react"; import axios from "axios"; import { Context } from "../../../context/Context"; export default function Login() { const userRef = useRef(); const passwordRef = useRef(); const { user, dispatch, isFetching } = useContext(Context); const handleSubmit = async (e) => { e.preventDefault(); dispatch({ type: "LOGIN_START" }); try { const res = await axios.post("/auth/login", { username: userRef.current.value, password: passwordRef.current.value, }); dispatch({ type: "LOGIN_SUCCESS", payload: res.data }); } catch (err) { dispatch({ type: "LOGIN_FAILURE" }); } }; console.log(user) return ( <div className="login"> <span className="loginTitle">Login</span> <form className="loginForm" onSubmit={handleSubmit}> <label>Username</label> <input className="loginInput" type="text" placeholder="Enter your username..." ref={userRef} /> <label>Password</label> <input className="loginInput" type="password" placeholder="Enter your password..." ref={passwordRef} /> <button className="loginButton" type="submit">Login</button> </form> <button className="loginRegisterButton"> <Link className="link" to="/register">Register</Link> </button> </div> ); }
问题原因及修复
错误根源在login接口的逻辑判断:当!user或!validated时,你用&&直接发送响应,但未终止后续代码执行。比如用户不存在时,!user && res.status(400).json("Wrong credentials!")发送一次响应后,代码仍会继续执行,尝试访问user.password(此时user为undefined,触发catch),catch里又发送一次500响应,导致重复发送响应头。
修复方法:发送错误响应后用return终止函数,或改用if-else结构:
修复后的login接口代码
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!"); } const { password, ...others } = user._doc; res.status(200).json(others); } catch (err) { res.status(500).json(err); } });
通过if判断加return,确保发送错误响应后直接结束函数,避免后续代码执行引发的重复响应问题。
内容的提问来源于stack exchange,提问作者Raghav Mittal
相关产品推荐
相关产品推荐

