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

Nest.js中使用Interceptor修改响应数据无效问题求助

NestJS Interceptor无法修改响应的问题解决

问题场景

使用NestJS的ResTransformerInterceptor统一将响应字段转为蛇形命名,但控制器中使用@Res()直接发送响应后,Interceptor未生效,snakeCase函数本身功能正常。

拦截器代码

import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import { map, Observable } from 'rxjs';
import { snakeCase } from './utils'

@Injectable()
export class ResTransformerInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    let request = context.switchToHttp().getRequest()
    return next
      .handle()
      .pipe(
        map((response) => {
          console.log(response)
          response = snakeCase(response)
          return response
        })
      )
  }
}

控制器代码

import { Body, Controller, Get, Post, Res, UseGuards, UseInterceptors } from '@nestjs/common';
import { Response } from 'express';
import { IUser } from 'src/utils/interfaces';
import { ResTransformerInterceptor } from 'src/utils/res-transformer.interceptor';
import { AuthService } from './auth.service';
import { RegisterUserDto, LoginDto, OtpDto, ForgetPassDto } from './dto/auth.dto';
import { JwtAuthGuard } from './jwt-auth.guard';
import { User } from './user.decorator';

@Controller('auth')
export class AuthController {
    constructor(private readonly authService: AuthService) { }

    @UseGuards(JwtAuthGuard)
    @UseInterceptors(new ResTransformerInterceptor)
    @Get('/user')
    async show(
        @User() user: IUser,
        @Res() response: Response) {
        const { data, statusCode } = await this.authService.showUser(user.userId)
        return response.status(statusCode).send(data)
    }
}

问题原因

当控制器方法中注入@Res()(未添加passthrough选项)时,NestJS会将响应处理的控制权完全移交至开发者,此时方法的返回值会被框架忽略,Interceptor的map操作无法捕获到响应数据——因为直接调用response.send()会绕过NestJS内置的响应处理管道,Interceptor仅对框架管理的响应数据流生效。

解决方案

有两种可行的修复方式,根据需求选择:

方案1:移除@Res()依赖,让NestJS自动处理响应

直接返回数据,并通过@HttpCode()装饰器设置固定状态码,或动态抛出HttpException适配动态状态码:

import { HttpCode, HttpException } from '@nestjs/common';

// ...其他代码

@UseGuards(JwtAuthGuard)
@UseInterceptors(new ResTransformerInterceptor)
@Get('/user')
async show(@User() user: IUser) {
    const { data, statusCode } = await this.authService.showUser(user.userId)
    // 方式1:状态码固定时使用@HttpCode
    // @HttpCode(200)
    // return data;

    // 方式2:状态码动态调整时使用HttpException
    throw new HttpException(data, statusCode);
}

方案2:保留@Res()但启用passthrough选项

通过@Res({ passthrough: true })注入响应对象,仅设置状态码,不直接调用send(),而是返回数据让NestJS处理,确保Interceptor能捕获到响应流:

@UseGuards(JwtAuthGuard)
@UseInterceptors(new ResTransformerInterceptor)
@Get('/user')
async show(
    @User() user: IUser,
    @Res({ passthrough: true }) response: Response) {
    const { data, statusCode } = await this.authService.showUser(user.userId)
    response.status(statusCode); // 仅设置状态码
    return data; // 返回数据,交由NestJS处理,Interceptor会修改该返回值
}

两种方案都能让ResTransformerInterceptor正常工作,将响应字段转为蛇形命名。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 07:35:20