-
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.
Refer to the comments below, corresponding to chapter sections, to guide you through the code changes for nest cats as you proceed through the docs chapter.
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
:
@Get('kaboom')
badRoute() {
throw new Error('kaboom');
}
http GET :3000/cats/kaboom
Note that Nest captures this error and prints the stack trace.
[Nest] 2972 - 08/27/2019, 12:19 PM [ExceptionsHandler] kaboom +19224ms Error: kaboom at CatsController.badRoute (E:\code\nest-cats\dist\cats\cats.controller.js:23:15) at E:\code\nest-cats\node_modules@nestjs\core\router\router-execution-context.js:36:29 ...
Node has not crashed; you can see this by issuing this request multiple times.
As described in the Base exceptions section of the docs, you can throw Nest's built-in HttpException
. To make testing easier, make a slight change to the code shown in the documentation. Rather than modifying the findAll()
method, add the following new route to the CatsController
:
@Get('httpexcep')
async getExcep() {
throw new HttpException({
status: HttpStatus.FORBIDDEN,
error: 'This is a custom message',
}, 403);
}
As mentioned in the docs, you'll also need to import HttpStatus
from @nestjs/common
. You should also import HttpException
from @nestjs/common
.
http GET :3000/cats/httpexcep
Continue reading until you get to the next Exception filters section.
As explained in the Exception filters section of the docs, go ahead and create the HttpExceptionFilter
class in a file called src/common/filters/http-exception.filter.ts
, copying the code from that section of the docs. You'll notice from the file path we specified just now that, just as we did with the logging middleware in the last chapter, we'll create this class inside a dedicated filters
folder in the src/common
folder. The folder structure should now look like:
nest-cats
└───src
└───cats
│ └───dto
│ └───interfaces
└───common
└───filters
└───middleware
Continue reading until you get to the Binding filters section.
Similar to what's explained in the docs, here, let's bind the exception. Varying slightly from the docs to ease testing, bind the exception filter to the GET /cats/httpexcep
route we created a few minutes ago.
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`;
}
}
Continue to read through to the end of the chapter, but we've now completed the code changes for nest-cats. You can test it as described below.
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 now handling this exception, replacing our custom exception message thrown in the route handler. The response should look like:
{
"path": "/cats/httpexcep",
"statusCode": 403,
"timestamp": "2019-08-25T16:06:40.158Z"
}
Next up is the Pipes chapter.