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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 05:48:12