Guards, interceptors, and exception filters all receive an ExecutionContext object. This lesson explains what it represents and how it provides a platform-agnostic view of the current request.
What Is ExecutionContext?
ExecutionContext extends Nest's simpler ArgumentsHost with additional methods for inspecting the current handler and its class, letting the same guard or interceptor work correctly whether it's applied to an HTTP route, a WebSocket event, or a microservice message pattern.
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
const handler = context.getHandler(); // the route method itself
const controllerClass = context.getClass(); // the controller class
return true;
}
switchToHttp() narrows the generic context to an HTTP-specific one, exposing getRequest() and getResponse(). Equivalent methods exist for WebSockets (switchToWs()) and RPC/microservices (switchToRpc()).
switchToHttp(), switchToWs(), and switchToRpc() adapt the context to a specific transport.
getHandler() returns the actual method reference, useful with Reflector to read metadata.
getClass() returns the controller class, for class-level metadata.
ArgumentsHost is the more limited base interface used inside exception filters.
ExecutionContext Cheatsheet
The context object shared by guards, interceptors, and filters.
Method
Returns
switchToHttp()
HTTP-specific context with getRequest()/getResponse()
switchToWs()
WebSocket-specific context
switchToRpc()
Microservice/RPC-specific context
getHandler()
Reference to the matched route handler method
getClass()
Reference to the matched controller class
Why This Abstraction Matters
Without ExecutionContext, a guard written for HTTP routes would need entirely different code to work with WebSocket gateways or microservice controllers. Because Nest normalizes all of these behind one interface, the same RolesGuard you wrote for REST routes can often be reused unchanged for WebSocket events.
Reading Metadata Through the Context
Combining context.getHandler() and context.getClass() with Reflector.getAllAndOverride() is the standard pattern for reading custom decorator metadata (like @Roles() or @Public()) from inside a guard or interceptor.
Common Mistakes
Calling switchToHttp() inside a guard meant to also support WebSocket or microservice contexts.
Manually branching on transport type instead of using the appropriate switchTo*() method.
Forgetting that getHandler() returns the method reference, not its name as a string.
Confusing ExecutionContext with the more limited ArgumentsHost used inside exception filters.
Key Takeaways
ExecutionContext gives guards, interceptors, and filters a transport-agnostic view of the current request.
switchToHttp(), switchToWs(), and switchToRpc() adapt the context to a specific transport.
getHandler() and getClass() are the standard way to read custom decorator metadata.
This abstraction is what lets the same guard or interceptor work across HTTP, WebSockets, and microservices.
Pro Tip
When writing a reusable guard or interceptor meant to work across transports, always go through context.switchToHttp() (or the matching method) rather than assuming the request object's shape, it's what makes the same class portable to WebSocket gateways later without a rewrite.
You now understand ExecutionContext. Next, move into Pipes, which transform and validate data before it reaches your handlers.