One of the the core principles of Nest.js development is developing scalable and maintainable applications. To acheive this goal, Interceptors offer an effective way for modifying and enhancing responses. Understanding and leveraging interceptors can significantly enhance the structure and effectiveness of your application, regardless of whether you're developing an API for a web service or a mobile app.
Interceptors are a type of middleware in Nest.js, located between the outgoing response and incoming request.
They can do all the following since they manage the life cycles of request and response:
Modify the request before it reaches the handler.
Transform the response data.
Implement cross-cutting concerns like logging, authentication, and caching.
They are class-based and implement the NestInterceptor interface.
They work seamlessly with Observables from RxJS, which is a fundamental part of Nest.js’s architecture.
This interceptor will wrap all responses in a standard structure containing data and optional meta fields.
Use following command or create the file manually:
nest g interceptor response-transform
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import { Observable, map } from 'rxjs';
@Injectable()
export class ResponseTransformInterceptor<T>
implements NestInterceptor<T, { data: T; meta?: any }>
{
intercept(
context: ExecutionContext,
next: CallHandler,
): Observable<{ data: T; meta?: any }> {
return next.handle().pipe(
map((data) => ({
data,
meta: {
timestamp: new Date().toISOString(),
},
})),
);
}
}
In this example, the interceptor wraps the original response in an object with data and meta fields. The meta field includes a timestamp to show when the response was sent.
Applying Interceptor Globally
Use the app.useGlobalInterceptors method in the main application file to apply the interceptor globally,
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ResponseTransformInterceptor } from './../interceptors/res-transform.interceptor';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalInterceptors(new ResponseTransformInterceptor());
await app.listen(3001);
}
bootstrap();
Applying Interceptor locally
Use the @UseInterceptors decorator to apply the interceptor to a specific route or controller:
@Controller('products')
@UseInterceptors(ResponseTransformInterceptor)
export class ProductsController {
@Get()
getProducts() {
return [
{ id: 1, name: ”Washing machine”, price: 18999 },
{ id: 2, name: ”Airfryer”, price: 3599 },
];
}
}
When we hit a request to the products endpoint, the response will be transformed as follows:
{
"data": [
{ "id": 1, "name": "Washing machine", "price": 18999 },
{ "id": 2, "name": "Airfryer", "price": 3599 }
],
"meta": {
"timestamp": "2025-01-22T12:34:56.789Z"
}
}
Interceptors can handle more complex scenarios, such as:
Using interceptors for response transformation in Nest.js enhances code maintainability and consistency. By centralizing transformation logic, you can ensure a uniform API experience for your clients while keeping your controllers and services clean. Whether you need simple response formatting or advanced data manipulation, interceptors provide a flexible and efficient solution for your Nest.js applications.
Ready to transform your business with our technology solution? Contact Us today to Leverage Our NodeJS Expertise.
0