Express报错ERR_HTTP_HEADERS_SENT cookie校验后无法重定向
报错原因
你遇到的ERR_HTTP_HEADERS_SENT: Cannot set headers after they are sent to the client错误本质是同一个请求被多次发送响应:
- 路由进入后第一行就执行了
res.render('admin-login', { title:'Admin login'}),这行代码会立刻把登录页的响应头、页面内容返回给客户端,本次请求的响应流程已经结束 - 后面的数据库查询是异步操作,等查询执行完成、判断到cookie有效要执行
res.redirect('/home')时,响应早就发送完毕,没法再修改响应头实现重定向,就会抛出这个错误。
另外你的SQL语句里key是MySQL保留关键字,直接写在查询里存在触发语法错误的风险,需要加反引号包裹。
修复方案
调整代码执行顺序:先做cookie校验、数据库查询逻辑,只有当校验不通过的时候才渲染登录页,校验通过直接走重定向,保证每个请求分支只执行一次响应操作。
修复后完整代码
app.get('/admin-login', (req, res) => { const loginKey = req.cookies['loggedin'] // 不存在登录cookie,直接返回登录页 if (!loginKey) { return res.render('admin-login', { title: 'Admin login' }) } // 存在cookie则走数据库校验 connection.query('SELECT * FROM sync WHERE `key` = ?', [loginKey], (error, results) => { if (error) { console.error(error.message) // 数据库查询异常时返回登录页,可按需自定义错误提示 return res.render('admin-login', { title: 'Admin login', error: '登录状态校验失败,请重试' }) } // 校验通过,重定向到首页 if (results.length > 0) { return res.redirect('/home') } // 数据库未匹配到有效登录凭证,返回登录页 return res.render('admin-login', { title: 'Admin login' }) }) })
编码注意事项
- Express中同一个请求的处理链路里,
res.render/res.redirect/res.send/res.json这类发送响应的方法只能调用一次,调用后即代表本次请求响应完成 - 数据库查询、IO操作都是异步非阻塞的,不要在这类异步操作前提前发送响应
- 每个响应分支前加
return,避免逻辑穿透执行到后续的响应代码,触发重复响应错误
内容的提问来源于stack exchange,提问作者Iryi
相关产品推荐
相关产品推荐

