Node/Express+MySQL重复注册触发ERR_HTTP_HEADERS_SENT错误的原因与解决
问题:Express注册接口重复提交时出现
ERR_HTTP_HEADERS_SENT错误并崩溃 问题背景
我使用Node.js/Express搭配MySQL开发用户注册功能,注册控制器代码如下:
import {db} from "../db.js" import bcrypt from "bcryptjs" import jwt from "jsonwebtoken" export const register = (req, res)=>{ const q = "SELECT * FROM user WHERE email = ?" db.query(q, [req.body.email], (err, data)=>{ if(err) { console.log(err) return res.status(500).json(err) } if(data.length) return res.status(409).json("user already exsits") } ) //CREATE A NEW USER const salt = bcrypt.genSaltSync(10) const hashedPassword = bcrypt.hashSync(req.body.password, salt) const qr = "INSERT INTO user ( `username`, `email`, `password` ) VALUES (?)" const username = req.body.username const password = hashedPassword const email = req.body.email console.log( "username, email, password", username, email, password) const user = [username, email, password] db.query(qr, [user], (err, data)=>{ if(err) { console.log('error insertion', err) return res.status(500).json(err) } return res.status(200).json("user is created!") } ) }
首次注册用户时功能正常,但重复提交同一用户数据时,出现以下错误导致应用崩溃:
$ nodemon index.js [nodemon] 2.0.20 [nodemon] to restart at any time, enter `rs` [nodemon] watching path(s): *.* [nodemon] watching extensions: js,mjs,json [nodemon] starting `node index.js` request received API is listening on port 8080 username, email, password test test@me.com $2a$10$NJ0/NfzsMY3cBBcyjdnY7..1NYlta5FTQI.qa25x2dh56R3blnqYm /home/me/react-projects/catapp/back/node_modules/mysql/lib/protocol/Parser.js:437 throw err; // Rethrow non-MySQL errors ^ Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at new NodeError (node:internal/errors:400:5) at ServerResponse.setHeader (node:_http_outgoing:663:11) at ServerResponse.header (/home/me/react-projects/catapp/back/node_modules/express/lib/response.js:794:10) at ServerResponse.send (/home/me/react-projects/catapp/back/node_modules/express/lib/response.js:174:12) at ServerResponse.json (/home/me/react-projects/catapp/back/node_modules/express/lib/response.js:278:15) at Query.<anonymous> (file:///home/me/react-projects/catapp/back/controllers/auth.js:42:35) at Query.<anonymous> (/home/me/react-projects/catapp/back/node_modules/mysql/lib/Connection.js:526:10) at Query._callback (/home/me/react-projects/catapp/back/node_modules/mysql/lib/Connection.js:488:16) at Sequence.end (/home/me/react-projects/catapp/back/node_modules/mysql/lib/protocol/sequences/Sequence.js:83:24) at Query._handleFinalResultPacket (/home/me/react-projects/catapp/back/node_modules/mysql/lib/protocol/sequences/Query.js:149:8) { code: 'ERR_HTTP_HEADERS_SENT' } Node.js v18.13.0 [nodemon] app crashed - waiting for file changes before starting...
错误成因
这个错误的核心是尝试向客户端发送多次响应:
db.query是异步操作,当检查用户是否存在的查询返回"用户已存在"并调用return res.status(409).json(...)时,register函数并未停止执行,后续的密码哈希、插入用户数据库的代码仍会继续运行。- 当插入用户的查询完成后,代码再次调用
res.status(200).json(...)尝试发送第二次响应,但HTTP协议要求一个请求只能对应一个响应,因此Node.js抛出ERR_HTTP_HEADERS_SENT错误,导致应用崩溃。
解决方法
将创建用户的逻辑嵌套到检查用户是否存在的回调函数内部,确保只有在确认用户不存在时,才执行后续的创建流程,避免重复发送响应。
修正后的代码:
import {db} from "../db.js" import bcrypt from "bcryptjs" import jwt from "jsonwebtoken" export const register = (req, res)=>{ const q = "SELECT * FROM user WHERE email = ?" db.query(q, [req.body.email], (err, data)=>{ if(err) { console.log(err) return res.status(500).json(err) } // 用户已存在则直接返回响应,终止后续逻辑 if(data.length) return res.status(409).json("user already exists") // 仅当用户不存在时执行创建逻辑 const salt = bcrypt.genSaltSync(10) const hashedPassword = bcrypt.hashSync(req.body.password, salt) const qr = "INSERT INTO user ( `username`, `email`, `password` ) VALUES (?)" const username = req.body.username const password = hashedPassword const email = req.body.email console.log( "username, email, password", username, email, password) const user = [username, email, password] db.query(qr, [user], (err, data)=>{ if(err) { console.log('error insertion', err) return res.status(500).json(err) } return res.status(200).json("user is created!") } ) } ) }
另外,代码中exsits拼写错误,建议改为exists,避免语义混淆。
内容的提问来源于stack exchange,提问作者blnks
相关产品推荐
相关产品推荐

