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
相关产品推荐
相关产品推荐

