What is an Interceptor

Code Before and After the Handler

An interceptor wraps the handler. Code before next.handle() runs before the handler; RxJS operators on the returned stream run after it. It can change the result, replace it (cache), or add a timeout.

src/common/interceptors/timing.interceptor.ts

import { CallHandler, ExecutionContext, Injectable, Logger, NestInterceptor } from '@nestjs/common';
import { Observable, tap } from 'rxjs';

@Injectable()
export class TimingInterceptor implements NestInterceptor {
  private readonly logger = new Logger('Timing');

  intercept(context: ExecutionContext, next: CallHandler): Observable<unknown> {
    const handler = `${context.getClass().name}.${context.getHandler().name}`;
    const start = Date.now();                                   // BEFORE
    return next.handle().pipe(
      tap(() => this.logger.log(`${handler} took ${Date.now() - start}ms`)),   // AFTER
    );
  }
}

Example

curl -s http://localhost:3000/products > /dev/null

Example output

[Nest] 24001  - LOG [Timing] ProductsController.findAll took 12ms