Exception Filters
-- In Nest there's an exceptions layer, which responsibility is to catch the unhandled exceptions and - return the appropriate response to the end-user. -
- -
- Every exception is handled by the global exception filter and when it's unrecognized (not HttpException
or class that inherit HttpException
), a user receives the below JSON response:
-
{{ errorResponse }}
- HttpException
-
- There's a built-in HttpException
class inside the @nestjs/common
package. The core exception handler works with this class very well.
- When you throw HttpException
object, it'll be caught by handler and transformed to the relevant JSON response.
-
- In the CatsController
, we have a create()
method (POST
route). Let's assume that this route handler would throw an exception for some reason.
- We're gonna hardcode it:
-
Exception Filters
++ In Nest there's an + exceptions layer, which responsibility is to catch the unhandled exceptions and return the appropriate response + to the end-user. +
+ +
+ Every exception is handled by the global exception filter and when it's
+ unrecognized (not
+ HttpException
or class that inherit
+ HttpException
), a user receives the below JSON response:
+
{{ errorResponse }}
+ HttpException
+
+ There's a built-in
+ HttpException
class inside the
+ @nestjs/common
package. The core exception handler works with this class very well. When you throw
+ HttpException
object, it'll be caught by handler and transformed to the relevant JSON response.
+
+ In the
+ CatsController
, we have a
+ create()
method (
+ POST
route). Let's assume that this route handler would throw an exception for some reason. We're gonna hardcode
+ it:
+
{{ createMethod }}
- {{ createMethodJs }}
- - Warning I have used the-HttpStatus
here. It's a helper enum imported from the@nestjs/common
package. -
- Now when the client will call this endpoint, the response would looks like below: -
-{{ forbiddenResponse }}
-
- The HttpException
constructor takes string | object
as a first argument. If you'd pass object
instead of a string
, you'll completely override the response body.
-
{{ exceptionObj }}
- {{ exceptionObjJs }}
- - And that's how the response would look like: -
-{{ customResponse }}
- Exceptions Hierarchy
-
- The good practice is to create your own exceptions hierarchy. It means that every HTTP exception should inherit from the base HttpException
class.
- As a result Nest will recognize every of your exception, and will fully take care about the error responses.
-
{{ forbiddenException }}
-
- Since ForbiddenException
extends the base HttpException
,
- it will work well with the core exceptions handler, therefore we can use this class inside the create()
method.
-
{{ forbiddenCreateMethod }}
- {{ forbiddenCreateMethodJs }}
- HTTP exceptions
-
- To reduce the boilerplate code, Nest provides a set of usable exceptions that extends the core HttpException
. All of them are available in the @nestjs/common
package:
-
-
-
- BadRequestException -
- UnauthorizedException -
- NotFoundException -
- ForbiddenException -
- NotAcceptableException -
- RequestTimeoutException -
- ConflictException -
- GoneException -
- PayloadTooLargeException -
- UnsupportedMediaTypeException -
- UnprocessableException -
- InternalServerErrorException -
- NotImplementedException -
- BadGatewayException -
- ServiceUnavailableException -
- GatewayTimeoutException -
Exception Filters
-- The base exceptions handler is fine, but sometimes you may want to have a full control over the exceptions layer, for example, add some logging or use the different JSON schema. - We love generic solutions and making your life easier, that's why the feature called exception filters was created. -
-
- We're gonna create the filter, which responsibility is to catch the HttpException
and override the message
property.
-
{{ httpExceptionFilter }}
- {{ httpExceptionFilterJs }}
-
- The response
is a native express response object. The exception
is a currently processed exception.
-
- Hint Every exception filter should implement the-ExceptionFilter
interface. It forces to provide thecatch()
method with the proper signature. -
- The @Catch()
decorator binds the required metadata to the exception filter. It tells Nest that this filter is looking for HttpException
.
- The @Catch()
takes infinite count of parameters, so you can setup this filter for several types of exceptions, just separate them by a comma.
-
- The last step is to inform Nest that the HttpExceptionFilter
should be used within the create()
method.
-
{{ forbiddenCreateMethodWithFilter }}
- {{ forbiddenCreateMethodWithFilterJs }}
- - Warning The-@UseFilters()
decorator is imported from the@nestjs/common
package. -
- We've used the @UseFilters()
decorator here. Same as @Catch()
, it takes infinite count of parameters.
-
- In the above example, the HttpExceptionFilter
is applied only to the single create()
route handler, but it's not the only way.
- In fact, the exception filters can be method-scoped, controller-scoped and also global-scoped.
-
{{ controllerScopedFilter }}
-
- This construction setups the HttpExceptionFilter
for every route handler inside the CatsController
.
- It's the example of the controller-scoped exception filter. The last available scope is the global-scoped exception filter.
-
{{ globalScopedFilter }}
- - The global filters are used across the entire application, for every controller, every route handler. -
-
- Notice The useGlobalFilters()
method doesn't setup filters for gateways and microservices.
-
+ {{ createMethod }}
+ {{ createMethodJs }}
+ + Warning I have used the ++HttpStatus
here. It's a helper enum imported from the +@nestjs/common
package. +
+ Now when the client will call this endpoint, the response would looks like below: +
+{{ forbiddenResponse }}
+
+ The
+ HttpException
constructor takes
+ string | object
as a first argument. If you'd pass
+ object
instead of a
+ string
, you'll completely override the response body.
+
{{ exceptionObj }}
+ {{ exceptionObjJs }}
+ + And that's how the response would look like: +
+{{ customResponse }}
+ Exceptions Hierarchy
+
+ The good practice is to create your own
+ exceptions hierarchy. It means that every HTTP exception should inherit from the base
+ HttpException
class. As a result Nest will recognize every of your exception, and will fully take care about the
+ error responses.
+
{{ forbiddenException }}
+
+ Since
+ ForbiddenException
extends the base
+ HttpException
, it will work well with the core exceptions handler, therefore we can use this class inside the
+ create()
method.
+
{{ forbiddenCreateMethod }}
+ {{ forbiddenCreateMethodJs }}
+ HTTP exceptions
+
+ To reduce the boilerplate code, Nest provides a set of usable exceptions that extends the core
+ HttpException
. All of them are available in the
+ @nestjs/common
package:
+
-
+
-
+
BadRequestException
+
+ -
+
UnauthorizedException
+
+ -
+
NotFoundException
+
+ -
+
ForbiddenException
+
+ -
+
NotAcceptableException
+
+ -
+
RequestTimeoutException
+
+ -
+
ConflictException
+
+ -
+
GoneException
+
+ -
+
PayloadTooLargeException
+
+ -
+
UnsupportedMediaTypeException
+
+ -
+
UnprocessableException
+
+ -
+
InternalServerErrorException
+
+ -
+
NotImplementedException
+
+ -
+
BadGatewayException
+
+ -
+
ServiceUnavailableException
+
+ -
+
GatewayTimeoutException
+
+
Exception Filters
++ The base exceptions handler is fine, but sometimes you may want to have a + full control over the exceptions layer, for example, add some logging or use the different JSON schema. We love + generic solutions and making your life easier, that's why the feature called + exception filters was created. +
+
+ We're gonna create the filter, which responsibility is to catch the
+ HttpException
and override the
+ message
property.
+
{{ httpExceptionFilter }}
+ {{ httpExceptionFilterJs }}
+
+ The
+ response
is a native express
+ response object. The
+ exception
is a currently processed exception.
+
+ Hint Every exception filter should implement the ++ExceptionFilter
interface. It forces to provide the +catch()
method with the proper signature. +
+ The
+ @Catch(HttpException)
decorator binds the required metadata to the exception filter. It tells Nest that this filter
+ is looking for
+ HttpException
. The
+ @Catch()
takes endless number of parameters, so you can set up this filter for several types of exceptions, just
+ separate them by a comma.
+
+ The last step is to inform Nest that the
+ HttpExceptionFilter
should be used within the
+ create()
method.
+
{{ forbiddenCreateMethodWithFilter }}
+ {{ forbiddenCreateMethodWithFilterJs }}
+ + Warning The ++@UseFilters()
decorator is imported from the +@nestjs/common
package. +
+ We've used the
+ @UseFilters()
decorator here. Same as
+ @Catch()
, it takes endless number of parameters.
+
+ In the above example, the
+ HttpExceptionFilter
is applied only to the single
+ create()
route handler, but it's not the only way. In fact, the exception filters can be method-scoped, controller-scoped
+ and also global-scoped.
+
{{ controllerScopedFilter }}
+
+ This construction setups the
+ HttpExceptionFilter
for every route handler inside the
+ CatsController
. It's the example of the controller-scoped exception filter. The last available scope is the global-scoped
+ exception filter.
+
{{ globalScopedFilter }}
+ + The global filters are used across the entire application, for every controller, every route handler. +
+
+ Notice The
+ useGlobalFilters()
method doesn't setup filters for gateways and microservices.
+
+ Catch everything
+
+ To handle every occurred exception, you may leave parentheses empty (
+ @Catch()
):
+
{{ exceptionFilter }}
+ {{ exceptionFilterJs }}
+ Above filter will catch each thrown exception.
+Global filters
+
+ The global exception filters don't belong to any scope. They live outside modules, thus as a result - they can't inject dependencies.
+ We need to create an instance immediately. But quite often, global filters depend on other objects, for example, we'd
+ love to log an exception using
+ LoggerService
, but this service is a part of the
+ LoggerModule
. What's now?
+
+ The solution is pretty easy. Each Nest application instance is in fact, a created + Nest context. The Nest context is a wrapper around the Nest container, which holds all instantiated classes. + We can grab any existing instance from within any imported module directly using application object. +
+
+ Let's assume that we have a
+ LoggerExceptionFilter
registered in the
+ LoggerModule
. This
+ LoggerModule
is imported into
+ root module. We can pick the
+ LoggerExceptionFilter
instance using following syntax:
+
{{ getLoggerExceptionFilter }}
+
+ To grab LoggerExceptionFilter
instance we have used 2 methods, well-described in the below table:
+
+ get()
+ |
+ + Makes possible to retrieve the instance of the component or controller available inside the processed module. + | +
+ select()
+ |
+ + Allows you to navigate through the module tree, for example, to pull out a specific instance from the selected module. + | +
+ Hint The root module is selected by default. To select any other module, you need to go through entire modules stack (step by step). +