-
Notifications
You must be signed in to change notification settings - Fork 0
exception filters
With this chapter, if you want to follow along, check out the exception-filters-start
branch and go to the following along section.
If you just want a final version of the project as of the end of the chapter, check out the exception-filters-end
branch, and proceed to the Upon completion section.
As described in the docs, here, if you throw an exception from your code, it's caught by the built-in exception layer provided by Nest. To see this in action, add the following route to src/cats/cats.controller.ts
:
@Controller('cats')
export class CatsController {
@Get('bad')
badRoute() {
throw new Error('kaboom');
}
...
}
http GET :3000/cats/kaboom
As described in the docs, here, you can throw a Nest built-in HttpException
. Go ahead and update the CatsController
as shown in the fully overridden response body example (the code below):
@Get()
async findAll() {
throw new HttpException({
status: HttpStatus.FORBIDDEN,
error: 'This is a custom message',
}, 403);
}
http GET :3000/cats
As explained in the docs, here, go ahead and create the HttpExceptionFilter
class in a file called src/common/filters/http-exception.filter.ts
. Just as with the logging middleware, we'll do this in the src/common
folder, and we'll create a filters
folder to contain the class. The folder structure should now look like:
nest-cats
└───src
└───cats
│ └───dto
│ └───interfaces
└───common
└───filters
└───middleware
Similar to what's explained in the docs, here, let's bind the exception. Varying slightly from the docs to ease testing, let's create a new route for testing the exception filter.
We'll add an endpoint GET /httpexcep
and bind the exception filter to that route. You can use either the instance (e.g., @UseFilters(new HttpExceptionFilter()))
or the class (e.g., @UseFilters(HttpExceptionFilter))
. The docs explain the trade-offs.
Here's what src/cats/cats.controller.ts
should look like now:
import {
Controller,
Get,
Post,
Param,
Body,
Put,
Delete,
HttpStatus,
HttpException,
UseFilters,
} from '@nestjs/common';
import { CreateCatDto, UpdateCatDto } from './dto';
import { CatsService } from './cats.service';
import { Cat } from './interfaces/cat.interface';
import { HttpExceptionFilter } from '../common/filters/http-exception.filter';
@Controller('cats')
export class CatsController {
constructor(private readonly catsService: CatsService) {}
@Get('kaboom')
badRoute() {
throw new Error('kaboom');
}
@Post()
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}
@Get()
async findAll(): Promise<Cat[]> {
return this.catsService.findAll();
}
// route to test our HttpExceptionFilter
@Get('httpexcep')
@UseFilters(HttpExceptionFilter)
async getExcep() {
throw new HttpException(
{
status: HttpStatus.FORBIDDEN,
error: 'This is a custom message',
},
403
);
}
@Get(':id')
findOne(@Param('id') id: string) {
return `This action returns a #${id} cat`;
}
@Put(':id')
update(@Param('id') id: string, @Body() updateCatDto: UpdateCatDto) {
return `This action updates a #${id} cat`;
}
@Delete(':id')
remove(@Param('id') id: string) {
return `This action removes a #${id} cat`;
}
}
You now have an exception handler defined for the GET /cats
route. You can either proceed using your code, or if you've run into any issues, you can checkout the exception-filters-end
branch to get caught up with the code as of the end of this chapter.
You should now be able to test the app with some REST requests.
Test the exception filter by making a request to GET /cats
with:
http GET :3000/cats/httpexcep
Notice that the HttpExceptionFilter
is handling this exception, providing a standard response that looks like the following, replacing our custom exception message thrown in the route handler:
{
"path": "/cats/httpexcep",
"statusCode": 403,
"timestamp": "2019-08-25T16:06:40.158Z"
}
Next up is the Pipes chapter.