Создайте тот же формат ошибок, что и `class-validator` в NestJS - PullRequest
1 голос
/ 18 февраля 2020

Давайте иметь этот контроллер в проекте Nest JS:

  @Post('resetpassword')
  @HttpCode(200)
  async requestPasswordReset(
    @Body() body: RequestPasswordResetDTO,
  ): Promise<boolean> {
    try {
      return await this.authService.requestPasswordReset(body);
    } catch (e) {
      if (e instanceof EntityNotFoundError) {
        // Throw same exception format as class-validator throwing (ValidationError)
      } else throw e;
    }
  }

Определение Dto:

export class RequestPasswordResetDTO {
  @IsNotEmpty()
  @IsEmail()
  public email!: string;
}

Я хочу выдать ошибку в формате ValidationError (свойство, значение, ограничения, и т. д. c), когда this.authService.requestPasswordReset(body); создает исключение EntityNotFoundError.

Как я могу создать эту ошибку вручную? Эти ошибки просто выдаются, когда проверка DTO по class-validator завершается неудачно. И это могут быть просто stati c проверки, а не asyn c проверки базы данных.

Таким образом, окончательный формат ответа API должен быть, например:

{
    "statusCode": 400,
    "error": "Bad Request",
    "message": [
        {
            "target": {
                "email": "not@existing.email"
            },
            "value": "not@existing.email",
            "property": "email",
            "children": [],
            "constraints": {
                "exists": "email address does not exists"
            }
        }
    ]
}

Мне нужно, чтобы он был последовательная обработка ошибок:)

Ответы [ 2 ]

1 голос
/ 18 февраля 2020

Вы можете использовать Фильтр исключений , чтобы создать свой настраиваемый ответ на это исключение. Сначала мы определим Фильтр исключений:

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';
// import { EntityNotFoundError } from 'wherever';

@Catch(EntityNotFoundError)
export class EntityNotFoundExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const status = exception.getStatus();

    response
      .status(status)
      .json({
        "statusCode": 400,
        "error": "Bad Request",
        "message": [
          {
            "target": {},
            "property": "email",
            "children": [],
            "constraints": {
              "isEmail": "email must be an email"
            }
          },
          // other field exceptions
        ]
      });
  }
}

Затем вернемся в свой контроллер и используем фильтр:

  // ...
  import { EntityNotFoundExceptionFilter } from 'its module';
  // ...
  @Post('resetpassword')
  @HttpCode(200)
  @UseFilters(EntityNotFoundExceptionFilter)
  async requestPasswordReset(
    @Body() body: RequestPasswordResetDTO
  ): Promise<boolean> {
      return await this.authService.requestPasswordReset(body);
  }

Это должно работать просто отлично.

0 голосов
/ 30 апреля 2020

При добавлении ValidationPipe в ваше приложение укажите пользовательский exceptionFactory:

  app.useGlobalPipes(
    new ValidationPipe({
      exceptionFactory: (validationErrors: ValidationError[] = []) => {
        return new BadRequestException(validationErrors);
      },
    })
  );

. Это все, что вам нужно для получения желаемого результата.

Для сравнения: Вы можете проверить оригинальное гнездо JS версия здесь .

...