Next.js API创建用户后发邮件出现ERR_HTTP_HEADERS_SENT错误
问题原因
核心错误原因是接口逻辑中多次向客户端返回响应,Node.js的HTTP协议规则规定:响应一旦发送给客户端后,就不能再修改响应头或发送新的响应内容,否则就会触发ERR_HTTP_HEADERS_SENT报错。具体触发点如下:
- 用户保存成功后,你先执行了
res.send({ user: user._id }),已经完成了一次响应发送 - 后续代码继续执行发送邮件逻辑后,又调用了
res.status(200).json({ status: 'OK' }),尝试第二次发送响应,直接触发报错 - 如果用户保存触发catch逻辑,你在catch中返回400响应后没有终止代码执行,后续还是会执行发送邮件和第二次返回响应的逻辑,同样会触发报错
解决方案
调整接口逻辑,确保整个请求生命周期内只返回一次响应,修改点如下:
- 将发送邮件的逻辑移到try块内,放在用户保存成功之后
- 去掉重复的响应发送,邮件发送成功后统一返回一次响应
- catch块补全err参数,且返回响应后加return终止后续代码执行
修正后的接口代码如下:
import connectDB from '../../../lib/mongodb' import bcrypt from 'bcrypt' import User from '../../../models/user' const mail = require('@sendgrid/mail'); mail.setApiKey(process.env.SENDGRID_API_KEY); const handler = async (req, res) => { // 检查邮箱是否已存在 const emailExists = await User.findOne({ email: req.body.email }) if (emailExists) return res.status(400).send("Email already exists") // 加密密码 const salt = await bcrypt.genSalt(10) const hash = await bcrypt.hash(req.body.password, salt) const user = new User({ firstname: req.body.firstname, lastname: req.body.lastname, username: req.body.username, email: req.body.email, password: hash }) try { const savedUser = await user.save(); // 发送欢迎邮件 const message = ` First Name: ${req.body.firstname}\r\n Last Name: ${req.body.lastname}\r\n Username: ${req.body.username}\r\n Email: ${req.body.email} `; const data = { to: req.body.email, from: 'Ellis Development <hello@ebrookes.dev>', subject: `Welcome ${req.body.firstname} ${req.body.lastname} to Ellis Development`, text: message, html: message.replace(/\r\n/g, '<br />') }; await mail.send(data); // 统一返回一次响应 res.status(200).json({ user: savedUser._id, status: 'OK' }); } catch (err) { // 返回错误后终止执行 return res.status(400).send(err) } } export default connectDB(handler)
如果不需要等待邮件发送结果再返回响应,可以把await mail.send(data)改为异步非阻塞写法,优化接口响应速度:
mail.send(data).catch(err => console.error('邮件发送失败:', err))
内容的提问来源于stack exchange,提问作者Ben Bagley
相关产品推荐
相关产品推荐

