ExecutionContext & ArgumentsHost: HTTP, WebSocket, and Microservice Abstraction
- Last updated
- Prerequisites:
- NestJS Guards and Interceptors
- HTTP vs WebSocket vs RPC transports
- nestjs
- execution-context
- arguments-host
- guards
- interceptors
- microservices
Read at your depth
The practical view
`ArgumentsHost` is an abstraction provided to filters, guards, and interceptors that gives access to the underlying protocol arguments. You use `host.switchToHttp()` (to get `req`, `res`), `host.switchToWs()` (to get `client`, `data`), or `host.switchToRpc()` (to get `data`, `context`). `ExecutionContext` extends `ArgumentsHost` by adding metadata about the current controller class (`context.getClass()`) and method handler (`context.getHandler()`).
The same idea in other frameworks
`context.switchToHttp().getRequest()` / `context.getHandler()`.Spring `HandlerMethod` and `ServletServerHttpRequest`.Starlette `Request` and ASGI `scope` dictionary.Express `(req, res, next)` raw middleware arguments.Legacy vs modern
Express-Coupled Middleware vs Multi-Protocol ExecutionContext Guard
Hardcoding `req.headers` breaks WebSockets and RPC; `ExecutionContext` provides multi-protocol abstraction.
const req = context.getArgs()[0]; // ❌ Breaks in WebSockets / Microservicesconst req = context.switchToHttp().getRequest(); const handler = context.getHandler(); // ✅ NEWInterview gotchas
Context
Interviewers test your precision with NestJS core interface hierarchies.
The mechanical answer
`ArgumentsHost` provides access *only* to the underlying transport arguments (`switchToHttp()`, `switchToWs()`, `switchToRpc()`, `getArgs()`). It is passed to Exception Filters. `ExecutionContext` **extends `ArgumentsHost`** and adds metadata about the execution pipeline: `getClass()` (the Controller class constructor) and `getHandler()` (the route handler method reference). It is passed to Guards and Interceptors.
Trap
Exception Filters receive `ArgumentsHost`, not `ExecutionContext`, so they cannot call `context.getHandler()`.
Context
Checks knowledge of reflection and role-based access control.
The mechanical answer
Inject the `Reflector` service and call `reflector.get('roles', context.getHandler())` or `reflector.getAllAndOverride('roles', [context.getHandler(), context.getClass()])` to merge and override class-level metadata with method-level metadata.
Trap
Always pass `[context.getHandler(), context.getClass()]` to `getAllAndOverride` so method-level decorators take precedence over controller-level decorators.