Interceptor
An interceptor is a Provider that makes it possible to
- bind extra logic before / after route handlers are called
- this is possible because the provided
intercept()
method wraps both the request and response streams.- we are able to build custom logic that runs after due to the observable pattern.
- this is possible because the provided
- transform the result returned from a function
- transform the exception thrown from a function
- extend the basic function behavior
- completely override a function depending on specific conditions (e.g., for caching purposes)
These capabilities of interceptors are inspired by Aspect Oriented Programming (AOP)
- AOP itself is about adding behavior to existing code without modifying the code itself, allowing us to implement logic like "log all function calls when the function's name begins with 'set'"
- effectively, what we are doing here is injecting some custom logic immediately prior to some handler being called. Thus, we are adding functionlity, but the original code remains unaltered.
an interceptor class is annotated with the @Injectable()
decorator and implements the NestInterceptor
interface.
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
// Because the interceptor class implements the `NestInterceptor` class, our interceptor has access to the `intercept()` method
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
console.log('Before...');
const now = Date.now();
return next
.handle()
.pipe(
// tap() is from RxJS and is used to perform side-effects for notifications from the source observable
tap(() => console.log(`After... ${Date.now() - now}ms`)),
);
}
}
intercept()
The intercept
function returns an observable
Args:
- The
ExecutionContext
provides methods that allow us to query for information about the current execution process. CallHandler
provides access to the response stream
Backlinks