javascript Nestjs prisma全局异常处理程序状态始终为500

2w2cym1i  于 2023-04-28  发布在  Java
关注(0)|答案(4)|浏览(168)

这是所有例外。filter.ts

@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  constructor(private readonly httpAdapterHost: HttpAdapterHost) {}

  catch(exception: HttpException, host: ArgumentsHost) {
    const { httpAdapter } = this.httpAdapterHost;

    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const message = exception.message;
    const status =
      exception instanceof HttpException
        ? exception.getStatus()
        : HttpStatus.INTERNAL_SERVER_ERROR;
    console.log();

    const responseBody = {
      success: false,
      message,
    };

    httpAdapter.reply(ctx.getResponse(), responseBody, status);
  }
}

这是一个只返回一项的服务方法:

findOne(id: number) {
    return this.prisma.restaurant.findUniqueOrThrow({
      where: {
        id,
      },
    });
  }

问题是,如果没有找到该项,findUniqueOrThrow会抛出404。但是在全局过滤器中,当我记录状态时,我总是收到一个500状态代码。

gcuhipw9

gcuhipw91#

这里有一个完整的例子,过滤器处理时,棱镜。findFirstOrThrow抛出未找到异常:
notFound.filter.ts

import { ArgumentsHost, Catch, ExceptionFilter } from '@nestjs/common';
import { NotFoundError } from '@prisma/client/runtime';
import { Response } from 'express';

@Catch(NotFoundError)
export class NotFoundExceptionFilter implements ExceptionFilter {
  public catch(exception: NotFoundError, host: ArgumentsHost) {

    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    return response.status(404).json({ statusCode: 404, error: 'Not Found' });
  }
}

main.ts

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  ...
  app.useGlobalFilters(new NotFoundExceptionFilter());
  await app.listen(3000);
}

瞧!

ecfsfe2w

ecfsfe2w2#

prisma本身不会从Nest抛出HttpException,Nest是getStatus()方法存在的地方。抛出的错误也会使exception instanceof HttpException检查失败。您应该将调用 Package 在try/catch中,并将错误转换为适当的异常类型,以便Nest的过滤器可以处理发送回正确的异常状态代码

ar5n3qh5

ar5n3qh53#

我以前也遇到过这个问题。我认为你使用的是app.useGlobalFilters方法。尝试使用以下命令:

app.module.ts

import { APP_FILTER } from "@nestjs/common";

@Module(
 providers: [
   {
     provide: APP_FILTER,
     useClass: AllExceptionsFilter,
   }
 ]
)

这解决了我的问题。

piwo6bdm

piwo6bdm4#

建议将HttpExceptionFilterAllExceptionFilter分开。

@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  catch(exception: any, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const status = HttpStatus.INTERNAL_SERVER_ERROR;

    console.log(exception);

    response
      .status(status)
      .json(ResultFactory.getFailureResult(exception.message));
  }
}
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const status = exception.getStatus();

    console.log(exception);

    response
      .status(status)
      .json(ResultFactory.getFailureResult(exception.message));
  }
}

然后,将AllExceptionFilter应用于全局过滤器:

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // Filters
  app.useGlobalFilters(new AllExceptionsFilter());
  
  ...

  await app.listen(PORT);
}
bootstrap();

并将HttpExceptionFilter应用于您使用的Controller类。那么它可能具有比AllExceptionFilter更高的优先级。因此,由Prisma引起的httpExceptions被HttpExceptionFilter过滤,并且只有uncaughtExceptionAllExceptionFilter过滤。
下面的代码片段是上面的示例:

@ApiTags('인증/인가')
@Controller('api/users')
@UseFilters(HttpExceptionFilter)
export class UsersController {
  constructor(private readonly usersService: UsersService) {}
  
  @Post('/sign-up')
  async signup(@Body() createRequest: CreateUserRequest) {
    return await this.usersService.signup(createRequest);
  }
}

相关问题