From bf4590bd4c858fa615a2dcdbdd5c7e457e4c15f0 Mon Sep 17 00:00:00 2001 From: Ivan Li Date: Sun, 7 Mar 2021 16:20:41 +0800 Subject: [PATCH] =?UTF-8?q?feat(exception):=20=E4=BC=98=E5=8C=96=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E5=93=8D=E5=BA=94=E6=A0=BC=E5=BC=8F=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commons/filters/all.exception-filter.ts | 64 ++++++--------------- src/commons/pipes/sanitize.pipe.ts | 15 +++++ src/main.ts | 10 +++- src/pipelines/dtos/create-pipeline.input.ts | 4 +- src/pipelines/pipelines.service.ts | 4 +- 5 files changed, 47 insertions(+), 50 deletions(-) create mode 100644 src/commons/pipes/sanitize.pipe.ts diff --git a/src/commons/filters/all.exception-filter.ts b/src/commons/filters/all.exception-filter.ts index e5f202e..81863a3 100644 --- a/src/commons/filters/all.exception-filter.ts +++ b/src/commons/filters/all.exception-filter.ts @@ -1,55 +1,27 @@ import { - ArgumentsHost, - Catch, ExceptionFilter, + Catch, + ArgumentsHost, HttpException, - HttpStatus, } from '@nestjs/common'; -import { EntityNotFoundError } from 'typeorm/error/EntityNotFoundError'; +import { ApolloError } from 'apollo-server-errors'; -@Catch() -export class AllExceptionsFilter implements ExceptionFilter { - catch(exception: any, host: ArgumentsHost) { - const ctx = host.switchToHttp(); - const response = ctx.getResponse(); - const request = ctx.getRequest(); - - const status = - exception instanceof HttpException - ? exception.getStatus() - : HttpStatus.INTERNAL_SERVER_ERROR; - - if (exception instanceof HttpException) { - const ex = exception.getResponse(); - if (ex instanceof Object) { - response.status(status).json({ - ...ex, - timestamp: Date.now(), - path: request.url, - }); - } else { - response.status(status).json({ - message: ex, - timestamp: Date.now(), - path: request.url, - }); - } - } else if (exception instanceof EntityNotFoundError) { - response.status(HttpStatus.NOT_FOUND).json({ - message: '资源未找到!', - timestamp: Date.now(), - path: request.url, - }); +@Catch(HttpException) +export class HttpExceptionFilter implements ExceptionFilter { + catch(exception: HttpException, host: ArgumentsHost) { + const message = exception.message; + const extensions: Record = {}; + const err = exception.getResponse(); + if (typeof err === 'string') { + extensions.message = err; } else { - console.error('服务器内部错误'); - console.error(exception); - response.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ - code: status, - timestamp: new Date().toISOString(), - message: '服务器内部错误', - error: exception, - path: request.url, - }); + Object.assign(extensions, (err as any).extension); + extensions.message = (err as any).message; } + return new ApolloError( + message, + exception.getStatus().toString(), + extensions, + ); } } diff --git a/src/commons/pipes/sanitize.pipe.ts b/src/commons/pipes/sanitize.pipe.ts new file mode 100644 index 0000000..d63acf3 --- /dev/null +++ b/src/commons/pipes/sanitize.pipe.ts @@ -0,0 +1,15 @@ +import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common'; +import { sanitize } from '@neuralegion/class-sanitizer/dist'; + +@Injectable() +export class SanitizePipe implements PipeTransform { + transform(value: any, metadata: ArgumentMetadata) { + // console.log(value, typeof value); + if (value instanceof Object) { + value = Object.assign(new metadata.metatype(), value); + sanitize(value); + // console.log(value); + } + return value; + } +} diff --git a/src/main.ts b/src/main.ts index 2cb827e..8433793 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,11 +2,19 @@ import { ValidationPipe } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; +import { HttpExceptionFilter } from './commons/filters/all.exception-filter'; +import { SanitizePipe } from './commons/pipes/sanitize.pipe'; async function bootstrap() { const app = await NestFactory.create(AppModule); const configService = app.get(ConfigService); - app.useGlobalPipes(new ValidationPipe()); + app.useGlobalPipes(new SanitizePipe()); + app.useGlobalPipes( + new ValidationPipe({ + transform: true, + }), + ); + app.useGlobalFilters(new HttpExceptionFilter()); await app.listen(configService.get('http.port')); } bootstrap(); diff --git a/src/pipelines/dtos/create-pipeline.input.ts b/src/pipelines/dtos/create-pipeline.input.ts index 9e8d12a..e72c63c 100644 --- a/src/pipelines/dtos/create-pipeline.input.ts +++ b/src/pipelines/dtos/create-pipeline.input.ts @@ -1,7 +1,7 @@ import { InputType } from '@nestjs/graphql'; import { WorkUnitMetadata } from '../../pipeline-tasks/models/work-unit-metadata.model'; import { - IsInstance, + IsObject, IsOptional, IsString, IsUUID, @@ -22,6 +22,6 @@ export class CreatePipelineInput { name: string; @IsOptional() - @IsInstance(WorkUnitMetadata) + @IsObject() workUnitMetadata: WorkUnitMetadata; } diff --git a/src/pipelines/pipelines.service.ts b/src/pipelines/pipelines.service.ts index 6d7316d..b1f01fe 100644 --- a/src/pipelines/pipelines.service.ts +++ b/src/pipelines/pipelines.service.ts @@ -9,7 +9,9 @@ import { ListPipelineArgs } from './dtos/list-pipelines.args'; @Injectable() export class PipelinesService extends BaseDbService { - readonly uniqueFields: Array = ['branch', 'projectId']; + readonly uniqueFields: Array> = [ + ['branch', 'projectId'], + ]; constructor( @InjectRepository(Pipeline) readonly repository: Repository,