Overview

Cancel long-running requests. Supports per-route configuration via @Timeout decorator.

Features

  • Configurable timeout
  • @Timeout decorator
  • Custom error message
  • Environment-based default

Installation

npx hanma add timeout-interceptor --framework nest

Code

import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
  RequestTimeoutException,
  SetMetadata,
} from "@nestjs/common";
import { Observable, TimeoutError, throwError, timeout, catchError } from "rxjs";
import { Reflector } from "@nestjs/core";

export const TIMEOUT_KEY = "request_timeout";

/**
 * Set custom timeout for a route (in milliseconds).
 * 
 * Usage:
 * @Timeout(60000) // 60 seconds
 * @Post("upload")
 * upload() {}
 */

 
export const Timeout = (ms: number) => SetMetadata(TIMEOUT_KEY, ms);

@Injectable()
export class TimeoutInterceptor implements NestInterceptor {
  private readonly defaultTimeout: number;

  constructor(private reflector: Reflector) {
    this.defaultTimeout = parseInt(process.env.REQUEST_TIMEOUT || "30000", 10);
  }

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const timeoutValue =
      this.reflector.getAllAndOverride<number>(TIMEOUT_KEY, [
        context.getHandler(),
        context.getClass(),
      ]) || this.defaultTimeout;

    return next.handle().pipe(
      timeout(timeoutValue),
      catchError((err) => {
        if (err instanceof TimeoutError) {
          const request = context.switchToHttp().getRequest();
          return throwError(
            () =>
              new RequestTimeoutException(
                `Request to ${request.method} ${request.url} timed out after ${timeoutValue}ms`
              )
          );
        }
        return throwError(() => err);
      })
    );
  }
}

Usage

@Timeout(60000)
@Post('upload')
upload() {}

Dependencies

No external dependencies required.

Frequently Asked Questions

How do I install Timeout Interceptor?
Run the following command: npx hanma add timeout-interceptor --framework nest
How do I use this snippet?
Copy the code and paste it into your project. The snippet will be saved to src/interceptors/timeout.interceptor.ts.
Can I customize this snippet?
Yes! All snippets are copy-paste code that you own. Feel free to modify them to fit your needs.
Does this work with other frameworks?
This snippet is designed for the specific framework. Check the other framework pages for equivalent implementations.