You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写包裹所有HTTP请求的NestJS回调函数

实现全局HTTP请求前后日志(含耗时统计)

针对你遇到的问题——现有拦截器或中间件只能捕获请求开始,无法在响应完成时打印日志,以下是两种可行方案:

方案一:使用Nest拦截器(跨平台友好)

Nest的拦截器可以通过RxJS的tap操作符,在请求处理流的开始和结束阶段注入逻辑。当路由处理完成并返回响应时,tap会触发回调,此时就能计算耗时。

代码实现

创建一个日志拦截器:

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

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const startTime = Date.now();
    const request = context.switchToHttp().getRequest();
    console.log(`${startTime}ms HTTP request start ${request.method} ${request.url}`);

    // 处理完请求后执行的逻辑
    return next.handle().pipe(
      tap(() => {
        const elapsed = Date.now() - startTime;
        console.log(`${elapsed}ms Response delivered`);
      }),
    );
  }
}

全局注册

在main.ts中全局启用该拦截器:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { LoggingInterceptor } from './logging.interceptor';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalInterceptors(new LoggingInterceptor());
  await app.listen(3000);
}
bootstrap();

方案二:使用Express中间件(精准捕获响应完成时机)

如果你的项目基于Express,可以直接监听响应对象的finish事件——这个事件会在响应完全发送给客户端时触发,比拦截器的tap更精准(比如流式响应场景)。

代码实现

创建日志中间件:

import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class LoggingMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    const startTime = Date.now();
    console.log(`${startTime}ms HTTP request start ${req.method} ${req.url}`);

    // 监听响应完成事件
    res.on('finish', () => {
      const elapsed = Date.now() - startTime;
      console.log(`${elapsed}ms Response delivered`);
    });

    next();
  }
}

全局注册

在AppModule中配置中间件,对所有路由生效:

import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggingMiddleware } from './logging.middleware';

@Module({})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(LoggingMiddleware).forRoutes('*');
  }
}

方案对比

  • 拦截器:Nest框架的上层抽象,支持跨平台(切换到Fastify无需修改代码),适合普通JSON响应场景。
  • Express中间件:依赖Express生态,能精准捕获响应发送完成的时机,适合流式响应或需要严格监控响应生命周期的场景。

内容的提问来源于stack exchange,提问作者Paku

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 15:33:21