【发布时间】:2021-05-29 02:39:03
【问题描述】:
我正在尝试将生产错误日志设为默认值,并仅在 environment variable 为 development 时向用户显示其他内容。我正在尝试通过以下方式执行此操作,但我收到一条消息说Cannot set headers after they are sent to the client。
const ErrorClass = require('../routes/utils/ErrorClass');
const prodDBCastError = err => {
const message = `Invalid ${err.path}: ${err.value}`;
return new ErrorClass(message, 400);
};
const prodDBDuplicateFieldsError = err => {
const value = err.errmsg.match(/(["'])(\\?.)*?\1/)[0];
const message = `Duplicate field value: ${value}.`;
return new ErrorClass(message, 400);
};
const prodDBDValidationError = err => {
const errors = Object.values(err.errors).map(el => el.message);
const message = `Invalid input data. ${errors.join('. ')}`;
return new ErrorClass(message, 400);
};
const handleBadRequestDB = err => {
const errors = err.message;
const message = `Fixes: ${errors}`;
return new ErrorClass(message, 400);
};
const sendProdError = (err, res) => {
if (err.isOperationalError){
res.status(err.status).json({
status: err.status,
message: err.message,
});
} else {
res.status(500).json({
status: 'error',
message: 'Server Issue.',
});
}
};
const sendVerboseDevError = (err, res) => {
logger.error(err);
err.status = err.status || 500;
res.status(err.status).json({
status: err.status,
name: err.name,
path: err.path,
errors: err.errors,
message: err.message,
stack: err.stack,
});
};
module.exports = (err, req, res, next) => {
if (process.env.APP_ENV === 'development'){
sendVerboseDevError(err, res);
}
if (err.name === 'CastError') {err = prodDBCastError(err);}
if (err.name === 'MongoError') {err = prodDBDuplicateFieldsError(err);}
if (err.name === 'ValidationError') {err = prodDBDValidationError(err);}
if (err.name === 'Bad Request') {err = handleBadRequestDB(err);}
sendProdError(err, res);
};
这就是我的 ErrorClass 的样子:
class ErrorClass extends Error {
constructor(message, status) {
super(message);
this.status = status;
this.isOperationalError = true;
Error.captureStackTrace(this, this.constructor);
}
}
module.exports = ErrorClass;
【问题讨论】:
-
在您的错误处理程序中,您同时调用了
sendVerboseDevError(err, res);和sendProdError(err, res);,这意味着您调用了两次res.status(..).json(..),但在第一次调用后,与客户端的连接已关闭,无法发送更多数据这会导致错误。所以只调用其中一个函数,永远不要同时调用。 -
我想不出任何其他方法可以将
sendProdError作为基本情况并始终发送输出而不泄露太多细节,除非env var是development
标签: javascript node.js mongodb express error-handling