ExecutionContext
The ExecutionContext is a powerful object passed to Interceptors (and Guards) that provides deep introspection into the current execution process, including details about the Controller and Method being invoked.
Overview
NestJS is designed to work across multiple protocols: standard HTTP (Express/Fastify), Microservices (TCP, Redis, RabbitMQ), and WebSockets.
Because Interceptors can be used in all of these contexts, the framework provides the ExecutionContext. This class extends ArgumentsHost and acts as a generic wrapper around the underlying platform’s specific request/response objects, while also providing metadata about the NestJS classes being executed.
Key Concepts
switchToHttp(): Converts the generic context into an HTTP context, allowing you to access the standardRequestandResponseobjects.getClass(): Returns theTypeof the Controller class which the current route handler belongs to.getHandler(): Returns a reference to the specific handler method (the function itself) that is about to be executed.- Reflection: By passing
getClass()orgetHandler()to Nest’sReflectorutility, you can read custom decorators/metadata attached to those elements.
Code Examples
Accessing Request Data
To log or mutate the request inside an interceptor, you must unpack it from the context.
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class AuditInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
// 1. Switch to HTTP context
const httpContext = context.switchToHttp();
// 2. Extract the Express Request object
const request = httpContext.getRequest();
console.log(`Auditing request by user ${request.user.id} to ${request.url}`);
return next.handle();
}
}
Introspecting the Controller and Method
You can log exactly which class and method are handling the request.
@Injectable()
export class DebugInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
// Get the name of the Controller class (e.g., 'UsersController')
const className = context.getClass().name;
// Get the name of the method (e.g., 'findAll')
const handlerName = context.getHandler().name;
console.log(`[DEBUG] Invoking ${className}.${handlerName}()`);
return next.handle();
}
}
Best Practices
- Protocol Agnosticism: If you are writing an interceptor that will be used in both HTTP and WebSocket controllers, you must check the context type before extracting the request. Use
context.getType() === 'http'to ensure you safely extract the correct objects. - Use for Metadata: The
ExecutionContextis primarily used in Interceptors (and Guards) in conjunction with theReflectorto read metadata. For example, a caching interceptor can usecontext.getHandler()to read a@CacheTTL(60)decorator attached to a specific route, allowing it to know exactly how long to cache the response.