英文:
Why Node.js crashes with Headers already sent Error when handling errors in Express
问题
我使用Express创建一个用于用户注册的API端点。问题是,每当我发送一个请求来触发API端点的错误时,我的Node.js服务器就会崩溃,并显示以下消息:
node:internal/errors:491
[1] ErrorCaptureStackTrace(err);
[1] ^
[1]
[1] Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent
to the client
[1] at new NodeError (node:internal/errors:400:5)
[1] at ServerResponse.setHeader (node:_http_outgoing:663:11)
[1] at ServerResponse.header (D:\...\node_modules\express\lib\response.js:794:10)
[1] at ServerResponse.send (D:\...\node_modul
所以,每当发送错误(失败)响应时,Node.js服务器都会崩溃,但当发送成功响应时,它不会崩溃。所以我猜我在处理错误时出了问题?
我在这里做错了什么?以下是我的实现:
const registerUser = async (req: Request, res: Response) => {
try {
const userData = createUserSchema.parse(req.body) as User;
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(userData.password, salt);
const user = await db.user.create({
data: {
...userData,
password: hashedPassword,
},
});
return res.status(201).json({
status: 'success',
data: { name: user.name, email: user.email },
});
} catch (error) {
if (error instanceof z.ZodError) {
return res.status(422).json({
status: 'fail',
message: error.issues,
});
} else if (error instanceof Prisma.PrismaClientKnownRequestError) {
if (error.code === 'P2002') {
return res.status(409).json({
status: 'fail',
message: 'Email address is already in use',
});
}
}
return res.status(500).json({
status: 'fail',
message: 'Something went wrong',
});
}
};
英文:
I'm using Express to create an API endpoint for user registration. The problem is, whenever I send a request that will initiate an error to that API endpoint, my node.js server crashes and gives me the following message:
node:internal/errors:491
[1] ErrorCaptureStackTrace(err);
[1] ^
[1]
[1] Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent
to the client
[1] at new NodeError (node:internal/errors:400:5)
[1] at ServerResponse.setHeader (node:_http_outgoing:663:11)
[1] at ServerResponse.header (D:\...\node_modules\express\lib\response.js:794:10)
[1] at ServerResponse.send (D:\...\node_modul
So, the node.js server crashes whenever is sending an error (fail) response, but when it's sending success response it doesn't crash. So I guess I'm not handling errors proper here?
What I'm doing wrong here? Here is my implementation:
const registerUser = async (req: Request, res: Response) => {
try {
const userData = createUserSchema.parse(req.body) as User;
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(userData.password, salt);
const user = await db.user.create({
data: {
...userData,
password: hashedPassword,
},
});
return res.status(201).json({
status: 'success',
data: { name: user.name, email: user.email },
});
} catch (error) {
if (error instanceof z.ZodError) {
return res.status(422).json({
status: 'fail',
message: error.issues,
});
} else if (error instanceof Prisma.PrismaClientKnownRequestError) {
if (error.code === 'P2002') {
return res.status(409).json({
status: 'fail',
message: 'Email address is already in use',
});
}
}
return res.status(500).json({
status: 'fail',
message: 'Something went wrong',
});
}
};
I've tried to return error only for one case to see if these responses are conflicting but even if I have only one response, node.js server crashes.
答案1
得分: 1
这个错误是因为您尝试在响应头已经发送给客户端之后设置响应头。在Express中,在发送响应正文部分后,您不能再设置响应头。当您尝试在已经发送响应正文部分或成功响应后发送错误(失败)响应时,就会出现这个错误。
要解决这个问题,请确保在您的代码中适当地处理错误。确保您不会为单个请求向客户端发送多个响应。您可以使用Express错误处理中间件捕获错误并向客户端发送适当的响应,而不会引发"ERR_HTTP_HEADERS_SENT"错误。
尝试使用类似以下的中间件:
app.use((err, req, res, next) => {
console.error(err);
res.status(500).json({
status: 'fail',
message: '出现了问题',
});
});
使用Express中间件将节省您大量的工作。
https://expressjs.com/en/guide/using-middleware.html
英文:
This error occurs because you are trying to set the response headers after they have already been sent to the client. In Express, you cannot set response headers after sending a response body part. This error occurs when you try to send an error (fail) response after you have already sent a response body part or a success response.
To fix this, make sure you're handling errors appropriately in your code. Make sure you don't send more than one response to the client for a single request. You can use the Express Error Handling Middleware to catch errors and send an appropriate response to the client without throwing an "ERR_HTTP_HEADERS_SENT" error.
Try with middleware like this:
app.use((err, req, res, next) => {
console.error(err);
res.status(500).json({
status: 'fail',
message: 'Something went wrong',
});
});
https://expressjs.com/en/guide/using-middleware.html
Using express middlware will save you a lot of effort
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论