为何出现Error [ERR_HTTP_HEADERS_SENT]错误?多角色管理员博客问题
问题描述
我正在开发一个多角色管理员的博客网站,此前功能正常,添加用于校验登录状态的中间件后,出现Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client错误。当已登录的管理员访问登录页面,或未登录用户访问受保护的管理员页面时,都会触发该错误。
管理员路由代码(Admin Route JS)
const adminController = require("../controllers/adminController"); const adminAuth = require("../middlewares/adminAuth"); // Register new admin adminRouter.get("/register", adminAuth.isLogin, adminController.register); adminRouter.post("/register", adminController.registerSave); // Login adminRouter.get("/login", adminAuth.isLogout, adminController.login); adminRouter.post("/login", adminController.loginSave); // Logout adminRouter.get("/logout", adminAuth.isLogin, adminController.logOut); // Other pages adminRouter.get("/dashboard", adminAuth.isLogin, adminController.dashboard); adminRouter.get("/all-admin", adminAuth.isLogin, adminController.allAdmin); adminRouter.get("/all-post", adminAuth.isLogin, adminController.allPost);
管理员控制器代码(Admin Controller JS)
const login = async (req, res) => { res.render("admin/login", { title: "Log in" }); }; const loginSave = async (req, res) => { try { const email = req.body.adminEmail; const password = req.body.adminPassword; const adminEmailFind = await adminUser.findOne({ email: email }); if (adminEmailFind) { const adminPassMatch = await bcrypt.compare( password, adminEmailFind.password ); if (adminPassMatch) { req.session.user_id = adminEmailFind._id; req.session.isSuperAdmin = adminEmailFind.isSuperAdmin; req.session.isAdmin = adminEmailFind.isAdmin; if (adminEmailFind.isSuperAdmin == 1) { res.redirect("/admin/dashboard"); } else if (adminEmailFind.isSuperAdmin == 0 && userData.isAdmin == 1) { res.redirect("/admin/dashboard"); } else { res.render("admin/login", { title: "Login", statusColor: "#ef4444", message: "Sorry !! Admins can proceed only", }); } } else { res.render("admin/login", { title: "Login", statusColor: "#ef4444", message: "Email or Password does not match !!!", }); } } else { res.render("admin/login", { title: "Login", statusColor: "#ef4444", message: "Email could not be found !!!", }); } } catch (error) { console.log(error.message); } }; const dashboard = async (req, res) => { res.render("admin/index", { title: "Dashboard" }); };
管理员认证中间件代码(Admin Auth middleware)
const isLogin = async (req, res, next) => { try { if ( !req.session.user_id && !req.session.isSuperAdmin && !req.session.isAdmin ) { res.redirect("/admin/login"); } next(); } catch (error) { console.log(error.message); } }; const isLogout = async (req, res, next) => { try { if ( req.session.user_id && req.session.isSuperAdmin && req.session.isAdmin ) { res.redirect("/admin/dashboard"); } next(); } catch (error) { console.log(error.message); } }; module.exports = { isLogin, isLogout };
问题原因及解决方案
核心原因
中间件中执行res.redirect()后未终止后续逻辑,next()仍会继续执行,导致控制器再次发送响应(res.render()或res.redirect()),引发重复发送HTTP头的错误。
修复步骤
- 修正
isLogin中间件:在res.redirect()后添加return,阻止后续next()执行
const isLogin = async (req, res, next) => { try { if ( !req.session.user_id && !req.session.isSuperAdmin && !req.session.isAdmin ) { return res.redirect("/admin/login"); } next(); } catch (error) { console.log(error.message); } };
- 修正
isLogout中间件:同样在res.redirect()后添加return
const isLogout = async (req, res, next) => { try { if ( req.session.user_id && req.session.isSuperAdmin && req.session.isAdmin ) { return res.redirect("/admin/dashboard"); } next(); } catch (error) { console.log(error.message); } };
- 额外修复控制器bug:
loginSave中存在未定义变量userData,需替换为adminEmailFind
// 原代码 else if (adminEmailFind.isSuperAdmin == 0 && userData.isAdmin == 1) { // 修改为 else if (adminEmailFind.isSuperAdmin == 0 && adminEmailFind.isAdmin == 1) {
内容的提问来源于stack exchange,提问作者Amit Deka
相关产品推荐
相关产品推荐

