NestJs - отлов ошибок MongoDB с помощью специального фильтра и @Catch (MongoError) - PullRequest
0 голосов
/ 04 февраля 2019

Я использую NestJS для создания пользовательского API с MongoDB.У меня есть следующие настройки:

  // users.controller.ts

  @Post('sign-up')
  @UseFilters(MongoExceptionFilter)
  async signUp(@Body() createUserDto: CreateUserDto): Promise<any> {
    return await this.userService.signUp(createUserDto).catch(error => {
      throw new BadRequestException(error);
    });
  }
  // user.service.ts

  async signUp(createUserDto: CreateUserDto): Promise<User> {
  const createUser = new this.userModel(createUserDto);
    return await createUser.save();
  }
  // mongo-exception.filter.ts

  import { ArgumentsHost,Catch, ConflictException, ExceptionFilter } from '@nestjs/common';
  import { MongoError } from 'mongodb';

  @Catch(MongoError)
  export class MongoExceptionFilter implements ExceptionFilter {
    catch(exception: MongoError, host: ArgumentsHost) {
      console.log('>>>>>>>>>>>>>>>>>>>> exception: ', exception);
    }
  }
  // package.json
  "dependencies": {
    "@nestjs/common": "^5.4.0",
    "@nestjs/core": "^5.4.0",
    "@nestjs/jwt": "^0.2.1",
    "@nestjs/mongoose": "^5.2.2",
    "@nestjs/passport": "^5.1.0",
    "@nestjs/typeorm": "^5.2.2",
    "fancy-log": "^1.3.3",
    "mongoose": "^5.4.7",
    "nestjs-config": "^1.3.0",
    "passport": "^0.4.0",
    "passport-http-bearer": "^1.0.1",
    "passport-jwt": "^4.0.0",
    "reflect-metadata": "^0.1.12",
    "rimraf": "^2.6.2",
    "rxjs": "^6.2.2",
    "typeorm": "^0.2.12",
    "typescript": "^3.0.1",
    "util": "^0.11.1"
  },

Теперь, когда я делаю POST-вызов к маршруту / регистрации, save() должен вызываться в user.service.ts.Это все работает.Затем, когда я в следующий раз отправляю маршрут / регистрация, он должен вызвать ошибку MongoDB, поскольку пользователь с таким же адресом электронной почты уже существует (адрес электронной почты уникален и, следовательно, дублирует ключи).Я вижу, что ошибка выдается, когда я просто регистрирую ошибку в .catch(err => ...);, но проблема заключается в пользовательском MongoExceptionFilter.Я не буду вызывать ошибку MongoError.Когда я оставляю поле @Catch() пустым, оно срабатывает, но не может обработать исключение.

Что я делаю не так?Поскольку я увидел эту запись и использовал ее в качестве основы, я не могу заставить ее работать.Это обновление Mongoose или NestJS, почему оно больше не работает?

1 Ответ

0 голосов
/ 04 февраля 2019

Это потому, что вы конвертируете все ошибки в BadRequestExceptions, так что ваш MongoExceptionFilter не будет нести ответственность;он проверяет instanceof MongoError, который возвращает false для BadRequestException:

return await this.userService.signUp(createUserDto).catch(error => {
      throw new BadRequestException(error);
    });

Это происходит до запуска фильтров исключений;они всегда запускаются последними.


Удалите .catch() из вашего контроллера.Если вы действительно хотите преобразовать все другие исключения в BadRequestExceptions (400), то вы можете написать второй фильтр исключений, который обрабатывает все исключения, не обработанные MongoExceptionFilter:

@Catch()
export class BadRequestFilter implements ExceptionFilter {
  catch(exception: Error, host: ArgumentsHost) {
    const response = host.switchToHttp().getResponse();
    response.status(400).json({message: exception.message});
  }
}

и

@Catch(MongoError)
export class MongoFilter implements ExceptionFilter {
  catch(exception: MongoError, host: ArgumentsHost) {
    const response = host.switchToHttp().getResponse();
    if (exception.code === 11000) {
      response.status(400).json({ message: 'User already exists.' });
    } else {
      response.status(500).json({ message: 'Internal error.' });
    }
  }
}

Затем добавьте оба к вашему контроллеру (порядок важен!):

@UseFilters(BadRequestFilter, MongoFilter)
async signUp(@Body() createUserDto: CreateUserDto): Promise<any> {
...