NestJS响应拦截器应用
在NestJS中使用响应拦截器时遇到几个问题:
- 如何正确注册全局响应拦截器?我尝试在main.ts中使用useGlobalInterceptors但似乎不生效
- 响应拦截器中如何统一处理异常情况?目前我的拦截器会正常返回成功响应,但遇到异常时格式不一致
- 想给所有成功响应添加统一的timestamp和status字段,但发现部分第三方接口的响应结构被破坏了
- 如何根据不同的controller或路由动态调整响应格式?比如/admin和/api需要不同的包装格式
- 拦截器中对response数据进行修改时,有没有推荐的最佳实践?直接修改原始对象似乎有副作用
3 回复
在NestJS中,响应拦截器可以用于统一处理响应数据、添加日志、格式化输出等。例如,你可以创建一个全局的响应拦截器来为所有接口增加“success”字段。
- 创建拦截器:使用
nest generate interceptor response
命令生成response.interceptor.ts
。 - 在拦截器中实现逻辑,比如:
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@Injectable()
export class ResponseInterceptor<T> implements NestInterceptor<T, { success: boolean; data: T }> {
intercept(context: ExecutionContext, next: CallHandler): Observable<{ success: boolean; data: T }> {
return next.handle().pipe(
map(data => ({
success: true,
data,
})),
);
}
}
- 注册拦截器:在
app.module.ts
中使用app.useGlobalInterceptors
注册。
import { Module } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { ResponseInterceptor } from './response.interceptor';
@Module({
providers: [
{
provide: APP_INTERCEPTOR,
useClass: ResponseInterceptor,
},
],
})
export class AppModule {}
这样,所有接口返回的数据都会被拦截并加上success: true
字段。
在NestJS中,响应拦截器可以用于统一处理所有响应数据,比如添加公共字段、日志记录或格式化输出。首先,创建一个拦截器类实现 nest/http
的 Injectable
和 nest/core
的 NestInterceptor
接口。
例如,创建一个 LoggingInterceptor
来记录请求和响应时间:
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 start = Date.now();
return next.handle().pipe(
tap(() => {
const response = context.switchToHttp().getResponse();
const delta = Date.now() - start;
console.log(`${response.statusCode} ${context.getClass().name} ${context.getHandler().name} ${delta}ms`);
}),
);
}
}
然后,在模块的 providers
中注册拦截器:
import { Module, NestModule, MiddlewareConsumer, RequestMethod } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { LoggingInterceptor } } from './logging.interceptor';
@Module({
providers: [
{
provide: APP_INTERCEPTOR,
useClass: LoggingInterceptor,
},
],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {}
}
这样,所有接口都会经过这个拦截器,从而实现统一的日志记录功能。
在NestJS中,响应拦截器(Interceptor)允许你在方法执行前后添加额外的逻辑,常用于统一处理响应格式、日志记录等场景。下面是一个完整的响应拦截器实现示例:
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@Injectable()
export class TransformInterceptor<T> implements NestInterceptor<T, Response<T>> {
intercept(context: ExecutionContext, next: CallHandler): Observable<Response<T>> {
return next.handle().pipe(
map((data) => ({
statusCode: context.switchToHttp().getResponse().statusCode,
timestamp: new Date().toISOString(),
data,
})),
);
}
}
interface Response<T> {
statusCode: number;
timestamp: string;
data: T;
}
应用拦截器有三种方式:
- 全局应用(在main.ts中):
app.useGlobalInterceptors(new TransformInterceptor());
- 控制器级别应用:
@Controller('cats')
@UseInterceptors(TransformInterceptor)
export class CatsController {}
- 方法级别应用:
@Get()
@UseInterceptors(TransformInterceptor)
findAll() {
return this.catsService.findAll();
}
拦截器常见用途:
- 统一响应格式
- 添加响应头
- 记录响应时间
- 数据转换/净化
注意:当使用app.useGlobalInterceptors()
时,拦截器不会注入依赖,如需依赖注入请使用模块注册方式。