如何使用 nestjs 异常过滤器处理 objectionjs 上的错误?
How to handling error on objectionjs with nestjs exception filters?
我使用 Objection.js 作为我的 Nest.js 应用程序的 ORM。我尝试为 Http 异常和异议错误(ORM / 数据库错误)实现全局错误处理。假设我在插入相同的唯一值时出错,它会抛出 UniqueViolationError
。但是每次我在应用程序的 users.service.ts
(用户模块服务)部分抛出错误时,在服务上错误仍然是 UniqueViolationError
的实例但在过滤器上它变成了 HttpExceptionError
的实例因此我的过滤器不起作用。这是完整的代码:
errors.filters.ts
import {
ExceptionFilter,
Catch,
ArgumentsHost,
HttpException,
HttpStatus,
InternalServerErrorException,
} from '@nestjs/common';
import {
ValidationError,
NotFoundError,
DBError,
ConstraintViolationError,
UniqueViolationError,
NotNullViolationError,
ForeignKeyViolationError,
CheckViolationError,
DataError,
} from 'objection';
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
catch(exception: InternalServerErrorException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
const request = ctx.getRequest();
// All the errors here are instance of HttpException, it shouldn't be :(
if (exception instanceof ValidationError) {
switch (exception.type) {
case 'ModelValidation':
response.status(HttpStatus.BAD_REQUEST).send({
message: exception.message,
type: exception.type,
data: exception.data,
timestamp: new Date().toISOString(),
statusCode: HttpStatus.BAD_REQUEST,
path: request.url,
});
break;
case 'RelationExpression':
response.status(HttpStatus.BAD_REQUEST).send({
message: exception.message,
type: 'RelationExpression',
data: {},
timestamp: new Date().toISOString(),
statusCode: HttpStatus.BAD_REQUEST,
path: request.url,
});
break;
case 'UnallowedRelation':
response.status(HttpStatus.BAD_REQUEST).send({
message: exception.message,
type: exception.type,
data: {},
timestamp: new Date().toISOString(),
statusCode: HttpStatus.BAD_REQUEST,
path: request.url,
});
break;
case 'InvalidGraph':
response.status(HttpStatus.BAD_REQUEST).send({
message: exception.message,
type: exception.type,
data: {},
timestamp: new Date().toISOString(),
statusCode: HttpStatus.BAD_REQUEST,
path: request.url,
});
break;
default:
response.status(HttpStatus.BAD_REQUEST).send({
message: exception.message,
type: 'UnknownValidationError',
data: {},
timestamp: new Date().toISOString(),
statusCode: HttpStatus.BAD_REQUEST,
path: request.url,
});
break;
}
} else if (exception instanceof ConstraintViolationError) {
response.status(HttpStatus.BAD_REQUEST).json({
statusCode: HttpStatus.BAD_REQUEST,
timestamp: new Date().toISOString(),
message: exception.message,
type: 'ConstraintViolation',
path: request.url,
});
} else if (exception instanceof DBError) {
response.status(HttpStatus.INTERNAL_SERVER_ERROR).json({
statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
timestamp: new Date().toISOString(),
message: exception.message,
type: 'UnknownDBError',
path: request.url,
});
} else if (exception instanceof DataError) {
response.status(HttpStatus.BAD_REQUEST).json({
statusCode: HttpStatus.BAD_REQUEST,
timestamp: new Date().toISOString(),
message: exception.message,
type: 'InvalidData',
path: request.url,
});
} else if (exception instanceof CheckViolationError) {
response.status(HttpStatus.BAD_REQUEST).json({
statusCode: HttpStatus.BAD_REQUEST,
timestamp: new Date().toISOString(),
message: exception.message,
type: 'CheckViolation',
path: request.url,
});
} else if (exception instanceof ForeignKeyViolationError) {
response.status(HttpStatus.BAD_REQUEST).json({
statusCode: HttpStatus.BAD_REQUEST,
timestamp: new Date().toISOString(),
message: exception.message,
type: 'ForeignKeyViolation',
path: request.url,
});
} else if (exception instanceof NotNullViolationError) {
response.status(HttpStatus.BAD_REQUEST).json({
statusCode: HttpStatus.BAD_REQUEST,
timestamp: new Date().toISOString(),
message: exception.message,
type: 'NotNullViolation',
path: request.url,
});
} else if (exception instanceof UniqueViolationError) {
response.status(HttpStatus.CONFLICT).json({
statusCode: HttpStatus.CONFLICT,
message: exception.message,
timestamp: new Date().toISOString(),
type: 'UniqueViolation',
path: request.url,
});
} else if (exception instanceof NotFoundError) {
response.status(HttpStatus.NOT_FOUND).json({
statusCode: HttpStatus.NOT_FOUND,
timestamp: new Date().toISOString(),
message: exception.message,
type: 'NotFound',
path: request.url,
});
} else if (exception instanceof HttpException) {
response.status(HttpStatus.INTERNAL_SERVER_ERROR).json({
message: exception.message,
statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
type: 'HttpServerError',
timestamp: new Date().toISOString(),
path: request.url,
});
} else {
response.status(HttpStatus.INTERNAL_SERVER_ERROR).json({
type: 'UnknownErrorServer',
statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
timestamp: new Date().toISOString(),
path: request.url,
});
}
}
}
main.ts
import 'dotenv/config';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import * as requestIp from 'request-ip';
import { ValidationPipe } from '@nestjs/common';
import { AllExceptionsFilter } from './filters/errors.filter';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(requestIp.mw());
app.enableCors();
app.useGlobalPipes(
new ValidationPipe({
transform: true,
}),
);
app.useGlobalFilters(new AllExceptionsFilter());
// swagger documentations
const config = new DocumentBuilder()
.setTitle('SWAGGER')
.setDescription('SWWAAAAG')
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('docs', app, document);
await app.listen(4040);
}
bootstrap();
在 users.service.ts
上运行
try {
await this.modelQuery.query().insert({ name: 'Same name' })
} catch (error) {
// in here still UniqueViolationError
throm new Error(error)
}
为什么错误实例变了,如何让它不变?我在这里做错了什么?
看起来您的所有支票都已正确设置。但是发生的事情是你正在创建一个新的错误对象并抛出 that 而不是抛出原始错误对象,这意味着你所有的 instanceof
检查现在都没有用了,因为你'我投了 new Error()
。要么不捕获错误,要么捕获错误并在执行日志记录或任何需要的操作后重新抛出原始错误。
我使用 Objection.js 作为我的 Nest.js 应用程序的 ORM。我尝试为 Http 异常和异议错误(ORM / 数据库错误)实现全局错误处理。假设我在插入相同的唯一值时出错,它会抛出 UniqueViolationError
。但是每次我在应用程序的 users.service.ts
(用户模块服务)部分抛出错误时,在服务上错误仍然是 UniqueViolationError
的实例但在过滤器上它变成了 HttpExceptionError
的实例因此我的过滤器不起作用。这是完整的代码:
errors.filters.ts
import {
ExceptionFilter,
Catch,
ArgumentsHost,
HttpException,
HttpStatus,
InternalServerErrorException,
} from '@nestjs/common';
import {
ValidationError,
NotFoundError,
DBError,
ConstraintViolationError,
UniqueViolationError,
NotNullViolationError,
ForeignKeyViolationError,
CheckViolationError,
DataError,
} from 'objection';
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
catch(exception: InternalServerErrorException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
const request = ctx.getRequest();
// All the errors here are instance of HttpException, it shouldn't be :(
if (exception instanceof ValidationError) {
switch (exception.type) {
case 'ModelValidation':
response.status(HttpStatus.BAD_REQUEST).send({
message: exception.message,
type: exception.type,
data: exception.data,
timestamp: new Date().toISOString(),
statusCode: HttpStatus.BAD_REQUEST,
path: request.url,
});
break;
case 'RelationExpression':
response.status(HttpStatus.BAD_REQUEST).send({
message: exception.message,
type: 'RelationExpression',
data: {},
timestamp: new Date().toISOString(),
statusCode: HttpStatus.BAD_REQUEST,
path: request.url,
});
break;
case 'UnallowedRelation':
response.status(HttpStatus.BAD_REQUEST).send({
message: exception.message,
type: exception.type,
data: {},
timestamp: new Date().toISOString(),
statusCode: HttpStatus.BAD_REQUEST,
path: request.url,
});
break;
case 'InvalidGraph':
response.status(HttpStatus.BAD_REQUEST).send({
message: exception.message,
type: exception.type,
data: {},
timestamp: new Date().toISOString(),
statusCode: HttpStatus.BAD_REQUEST,
path: request.url,
});
break;
default:
response.status(HttpStatus.BAD_REQUEST).send({
message: exception.message,
type: 'UnknownValidationError',
data: {},
timestamp: new Date().toISOString(),
statusCode: HttpStatus.BAD_REQUEST,
path: request.url,
});
break;
}
} else if (exception instanceof ConstraintViolationError) {
response.status(HttpStatus.BAD_REQUEST).json({
statusCode: HttpStatus.BAD_REQUEST,
timestamp: new Date().toISOString(),
message: exception.message,
type: 'ConstraintViolation',
path: request.url,
});
} else if (exception instanceof DBError) {
response.status(HttpStatus.INTERNAL_SERVER_ERROR).json({
statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
timestamp: new Date().toISOString(),
message: exception.message,
type: 'UnknownDBError',
path: request.url,
});
} else if (exception instanceof DataError) {
response.status(HttpStatus.BAD_REQUEST).json({
statusCode: HttpStatus.BAD_REQUEST,
timestamp: new Date().toISOString(),
message: exception.message,
type: 'InvalidData',
path: request.url,
});
} else if (exception instanceof CheckViolationError) {
response.status(HttpStatus.BAD_REQUEST).json({
statusCode: HttpStatus.BAD_REQUEST,
timestamp: new Date().toISOString(),
message: exception.message,
type: 'CheckViolation',
path: request.url,
});
} else if (exception instanceof ForeignKeyViolationError) {
response.status(HttpStatus.BAD_REQUEST).json({
statusCode: HttpStatus.BAD_REQUEST,
timestamp: new Date().toISOString(),
message: exception.message,
type: 'ForeignKeyViolation',
path: request.url,
});
} else if (exception instanceof NotNullViolationError) {
response.status(HttpStatus.BAD_REQUEST).json({
statusCode: HttpStatus.BAD_REQUEST,
timestamp: new Date().toISOString(),
message: exception.message,
type: 'NotNullViolation',
path: request.url,
});
} else if (exception instanceof UniqueViolationError) {
response.status(HttpStatus.CONFLICT).json({
statusCode: HttpStatus.CONFLICT,
message: exception.message,
timestamp: new Date().toISOString(),
type: 'UniqueViolation',
path: request.url,
});
} else if (exception instanceof NotFoundError) {
response.status(HttpStatus.NOT_FOUND).json({
statusCode: HttpStatus.NOT_FOUND,
timestamp: new Date().toISOString(),
message: exception.message,
type: 'NotFound',
path: request.url,
});
} else if (exception instanceof HttpException) {
response.status(HttpStatus.INTERNAL_SERVER_ERROR).json({
message: exception.message,
statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
type: 'HttpServerError',
timestamp: new Date().toISOString(),
path: request.url,
});
} else {
response.status(HttpStatus.INTERNAL_SERVER_ERROR).json({
type: 'UnknownErrorServer',
statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
timestamp: new Date().toISOString(),
path: request.url,
});
}
}
}
main.ts
import 'dotenv/config';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import * as requestIp from 'request-ip';
import { ValidationPipe } from '@nestjs/common';
import { AllExceptionsFilter } from './filters/errors.filter';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(requestIp.mw());
app.enableCors();
app.useGlobalPipes(
new ValidationPipe({
transform: true,
}),
);
app.useGlobalFilters(new AllExceptionsFilter());
// swagger documentations
const config = new DocumentBuilder()
.setTitle('SWAGGER')
.setDescription('SWWAAAAG')
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('docs', app, document);
await app.listen(4040);
}
bootstrap();
在 users.service.ts
上运行
try {
await this.modelQuery.query().insert({ name: 'Same name' })
} catch (error) {
// in here still UniqueViolationError
throm new Error(error)
}
为什么错误实例变了,如何让它不变?我在这里做错了什么?
看起来您的所有支票都已正确设置。但是发生的事情是你正在创建一个新的错误对象并抛出 that 而不是抛出原始错误对象,这意味着你所有的 instanceof
检查现在都没有用了,因为你'我投了 new Error()
。要么不捕获错误,要么捕获错误并在执行日志记录或任何需要的操作后重新抛出原始错误。