Context
How do we intercept the external http calls made by our NestJs server, so we can log and better handle the errors?
NestJs Interceptors
are able to process the requests and the responses made via the controllers, not the external http calls that we might need as part of a controller request.
Solutions
One solution would be to add a catchError
on the http call. NestJs documentation provides a full example and extensive information on HttpModule
and HttpService
from @nestjs/axios package
.
What if we already have a couple of axios requests and we don't want to add catchError block on each request? Here comes the second solution: axios response interceptors and exception filters.
First, let's consider this call as part of our service, where (hypothetically) our http call will throw an error:
//app.service.ts
getCats(): Observable<any> {
return this.httpService.get('http://localhost:3001/cats').pipe(
map((data) => {
console.log('Do something');
return data;
}),
);
}
Let's configure the axios response interceptor
. We're going to add this snippet as part of the bootstrap function. All HttpService
methods return an AxiosResponse
wrapped in an Observable
object, responses that we're going to intercept via this code:
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { HttpService } from '@nestjs/axios';
import { InternalServerErrorException } from '@nestjs/common';
async function bootstrap() {
const httpService = new HttpService();
const app = await NestFactory.create(AppModule);
httpService.axiosRef.interceptors.response.use(
(response) => {
return response;
},
(error) => {
console.error('Internal server error exception', error);
throw new InternalServerErrorException();
},
);
await app.listen(3000);
}
Responses with status 2** will be handled by the first function, where we simply return the response. In case of error, we log the error and throw a built-in HTTP exception, InternalServerErrorException
. Of course, we can implement more advanced error handling here, throwing exceptions depending on the error that we get from the axios code and so on.
Next, what happens with our exception? It's going to be caught by the global http exception filter.
//http-exception.filter.ts
import { ArgumentsHost, Catch, ExceptionFilter, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status = exception.getStatus();
response.status(status).json({
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url
});
}
}
Now that we have the code for the exception filter, let's make the adjustments so we can use it:
//app.module.ts
providers: [
{
provide: APP_FILTER,
useClass: HttpExceptionFilter
}
]
//main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { HttpService } from '@nestjs/axios';
import { HttpExceptionFilter } from './http-exception.filter';
import { InternalServerErrorException } from '@nestjs/common';
async function bootstrap() {
const httpService = new HttpService();
const app = await NestFactory.create(AppModule);
//http-exception as global filter
app.useGlobalFilters(new HttpExceptionFilter());
httpService.axiosRef.interceptors.response.use(
(response) => {
return response;
},
(error) => {
console.error('Internal server error exception', error);
throw new InternalServerErrorException();
},
);
await app.listen(3000);
}
What we learned as part of this blogpost:
- how to make an external http call via the
HttpService
from@nestJs/axios
package - how to intercept the responses of the http calls and throw built-in http exceptions in case of error
- how to intercept the http exceptions via the global http exception filter
In-depth documentation on error handling, axios interceptors and exception filters can be found here:
✨Github repo with the NestJs setup, exception filter and axios interceptor!
Thank you for reading! 🐾
Top comments (0)