Reputation: 689
this is the all-exception.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);
}
}
and this is a service method that returning just one item:
findOne(id: number) {
return this.prisma.restaurant.findUniqueOrThrow({
where: {
id,
},
});
}
The problem is that findUniqueOrThrow will throw 404 if the item is not found. but in the global filter when I log the status, I always receive a 500 status code.
Upvotes: 1
Views: 3882
Reputation: 21
I recommend to segregate the HttpExceptionFilter and AllExceptionFilter.
@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));
}
}
Then, apply the AllExceptionFilter to global filter:
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Filters
app.useGlobalFilters(new AllExceptionsFilter());
...
await app.listen(PORT);
}
bootstrap();
And apply the HttpExceptionFilter to Controller class you using. Then that might have the higher priority than AllExceptionFilter
. So, httpExceptions caused by Prisma be filtered by HttpExceptionFilter
, and only uncaughtException
be filtered by AllExceptionFilter
.
Below code snippet is example for above:
@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);
}
}
Upvotes: 1
Reputation: 95
I was also facing this problem before. I think you are using app.useGlobalFilters
method. Try using this instead:
app.module.ts
import { APP_FILTER } from "@nestjs/common";
@Module(
providers: [
{
provide: APP_FILTER,
useClass: AllExceptionsFilter,
}
]
)
This solved my issue.
Upvotes: 0
Reputation: 1846
Here a full example for filter handling when Prisma.findFirstOrThrow throw not found exception:
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);
}
Et voila !
Upvotes: 1
Reputation: 70221
prisma
on it's own does not throw an HttpException
from Nest, which is where the getStatus()
method exists. The error thrown will also fail the exception instanceof HttpException
check. You should wrap the call in a try/catch
and transform the error to the appropriate exception type so that Nest's filter can handle sending back to proper exception status code
Upvotes: 0