NestJS 9.4.0集成Fastify崩溃,Passport报res.setHeader错误求助
NestJS 9.4.0 + Fastify + Throttler + Passport 兼容配置方案
问题根源
报错res.setHeader is not a function本质是Passport OAuth2策略依赖Express风格的响应对象API,而Fastify的Reply响应对象没有setHeader方法(Fastify使用reply.header()/reply.redirect()替代)。同时需确保Throttler在Fastify环境下正确适配。
解决方案
1. 安装Fastify Passport适配依赖
npm install fastify-passport fastify-passport-oauth2
2. 修改AppModule配置
替换默认Passport模块为Fastify兼容版本,同时调整Throttler配置为异步加载(更符合NestJS最佳实践):
import { Module } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { TypeOrmModule } from '@nestjs/typeorm'; import { ThrottlerModule } from '@nestjs/throttler'; import { FastifyPassportModule } from '@nestjs/passport/dist/fastify'; import { AuthModule } from './auth/auth.module'; import { UsersModule } from './users/users.module'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { TypeOrmConfigService } from './config/typeorm.config'; import { join } from 'path'; import { envSchema } from './config/env.schema'; @Module({ imports: [ ConfigModule.forRoot({ ignoreEnvFile: !!process.env.CI, envFilePath: join(__dirname, '..', '.env'), validationSchema: envSchema, }), TypeOrmModule.forRootAsync({ useClass: TypeOrmConfigService, }), // Throttler配置:适配Fastify环境 ThrottlerModule.forRootAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService) => ({ ttl: Number(configService.get('THROTTLER_TTL')), limit: Number(configService.get('THROTTLER_LIMIT')), storage: { store: 'redis', options: { url: `redis://${configService.get('REDIS_HOST')}:${configService.get('REDIS_PORT')}`, }, }, }), }), // Fastify兼容的Passport模块 FastifyPassportModule.registerAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: async (configService: ConfigService) => ({ defaultStrategy: configService.get('jwt.defaultStrategy'), }), }), AuthModule, UsersModule, ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
3. 适配Facebook OAuth策略
修改FacebookStrategy,重写redirect方法适配Fastify的Reply对象:
import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { Profile } from 'passport-facebook'; import { FastifyPassportStrategy } from '@nestjs/passport/dist/fastify'; import { Strategy } from 'passport-facebook'; @Injectable() export class FacebookStrategy extends FastifyPassportStrategy(Strategy, 'facebook') { constructor(configService: ConfigService) { super({ clientID: configService.get('FACEBOOK_CLIENT_ID'), clientSecret: configService.get('FACEBOOK_CLIENT_SECRET'), callbackURL: configService.get('FACEBOOK_CALLBACK_URL'), scope: 'email', profileFields: ['emails', 'name'], }); } async validate(accessToken: string, refreshToken: string, profile: Profile) { // 自定义用户验证逻辑 return { email: profile.emails[0].value, firstName: profile.name.givenName, lastName: profile.name.familyName, }; } // 重写redirect方法,适配Fastify响应对象 redirect(reply: any, url: string) { reply.redirect(url); } }
同时更新AuthModule导入Fastify Passport模块:
import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { FastifyPassportModule } from '@nestjs/passport/dist/fastify'; import { FacebookStrategy } from './strategies/facebook.strategy'; import { AuthService } from './auth.service'; import { AuthController } from './auth.controller'; @Module({ imports: [ConfigModule, FastifyPassportModule], providers: [AuthService, FacebookStrategy], controllers: [AuthController], exports: [FastifyPassportModule], }) export class AuthModule {}
4. 确保Throttler在Fastify下正常工作
如果遇到Throttler拦截异常,可自定义Fastify版本的ThrottlerGuard:
import { Injectable, ExecutionContext } from '@nestjs/common'; import { ThrottlerGuard } from '@nestjs/throttler'; import { FastifyRequest } from 'fastify'; @Injectable() export class FastifyThrottlerGuard extends ThrottlerGuard { getRequestResponse(context: ExecutionContext) { const http = context.switchToHttp(); return { req: http.getRequest<FastifyRequest>(), res: http.getResponse(), }; } }
在main.ts全局注册:
app.useGlobalGuards(new FastifyThrottlerGuard());
5. 最终main.ts配置
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { ConfigService } from '@nestjs/config'; import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify'; async function bootstrap() { const app = await NestFactory.create<NestFastifyApplication>( AppModule, new FastifyAdapter(), ); const configService = app.get(ConfigService); const port = configService.get<string>('PORT', '3000'); app.enableCors({ origin: '*', methods: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'], allowedHeaders: ['Content-Type', 'Authorization'], credentials: true, }); await app.listen(port, '0.0.0.0'); } bootstrap();
内容的提问来源于stack exchange,提问作者Tebyy
相关产品推荐
相关产品推荐

