What are Interceptors?
Interceptors in NestJS act as middleware that wraps around the execution of method handlers. They provide a powerful way to implement AOP concepts by letting you preprocess input, handle errors, or post-process output without modifying the core business logic.
Real-World Example: Logging and Response Transformation
Let’s build an interceptor to log requests and responses in a NestJS application. This is a common cross-cutting concern in production systems, where we need to track API usage for debugging and performance monitoring.
Creating the Logging Interceptor:
import {
Injectable,
NestInterceptor,
ExecutionContext,
CallHandler,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { Logger } from '@nestjs/common';
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
private readonly logger = new Logger(LoggingInterceptor.name);
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const request = context.switchToHttp().getRequest();
const { method, url, body } = request;
const startTime = Date.now();
this.logger.log(`Incoming Request: [${method}] ${url} - Payload: ${JSON.stringify(body)}`);
return next.handle().pipe(
tap((response) => {
const duration = Date.now() - startTime;
this.logger.log(`Outgoing Response: [${method}] ${url} - Duration: ${duration}ms - Response: ${JSON.stringify(response)}`);
}),
);
}
}
Applying the Interceptor Globally
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { LoggingInterceptor } from './logging.interceptor';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalInterceptors(new LoggingInterceptor());
await app.listen(3000);
}
bootstrap();
Output Example
When making a GET request, the logs will look like this:
[Nest] 12345 - 2024-11-23T12:00:00Z LOG [LoggingInterceptor] Incoming Request: [GET] /api - Payload: {}
[Nest] 12345 - 2024-11-23T12:00:00Z LOG [LoggingInterceptor] Outgoing Response: [GET] /api - Duration: 2ms - Response: {"message":"This is a GET response"}