解决Node.js signup接口添加res.status(201).json时ERR_HTTP_HEADERS_SENT报错
错误原因
- 这个
ERR_HTTP_HEADERS_SENT错误的本质是同一个HTTP请求内多次向客户端发送响应,你现在的代码里在注册逻辑的if分支中,无论try块执行成功还是catch块触发,后续都会执行res.redirect('/'),也就是:- 注册成功时,先执行
res.status(201).json({ email })发送了第一次响应,紧接着执行res.redirect('/')尝试发送第二次响应 - 注册失败进入catch块时,先执行
res.status(400).send('Error, user not created')发送第一次响应,紧接着还是会执行res.redirect('/')尝试第二次响应
- 注册成功时,先执行
- 除此之外你当前代码还有两个潜在问题:
bcrypt.hashSync('password', 10)写死了密码字符串,没有使用用户提交的password变量,会导致所有用户的密码哈希值完全相同- 整个
handleErrorSignup的Promise链没有添加catch捕获异常,依旧可能抛出未处理的Promise拒绝警告
解决方案
- 每次调用
res发送响应的方法后添加return,阻止后续代码继续执行;如果是纯接口场景不需要页面跳转,直接删掉多余的res.redirect('/')即可 - 修复bcrypt加密的传参错误
- 给Promise链补充catch捕获全局异常,避免遗漏未处理的错误
修复后代码示例
module.exports.signup_post = async (req, res ) => { try { const { firstname, lastname, email, password } = req.body; const errors = await handleErrorSignup(firstname.trim(), lastname.trim(), email.trim(), password.trim()); if(errors.firstname === '' && errors.lastname === '' && errors.email === '' && errors.password === '') { // 修复密码传参错误,改为使用用户提交的password变量 const hash = bcrypt.hashSync(password, 10); try { await db.none('INSERT INTO users(firstname, lastname, email, password) VALUES($1, $2, $3, $4)', [firstname, lastname, email, hash]); const token = createToken(email); res.cookie('jwt', token, { httpOnly: true, maxAge: maxAge * 1000 }); // 发送响应后加return终止后续代码执行 return res.status(201).json({ email }); } catch(err) { return res.status(400).send('Error, user not created'); } } else { return res.status(400).json({ errors }); } } catch (globalErr) { // 捕获全局异常避免未处理的Promise拒绝警告 return res.status(500).send('Server internal error'); } }
内容的提问来源于stack exchange,提问作者supmethods
相关产品推荐
相关产品推荐

