REST 模块中的 Nest JS Throttler Guard 正在破坏 GraphQL 模块

G. *_*hka 2 rest node.js typescript graphql nestjs

我有一个带有 REST 模块和 GraphQL 模块的Nest.js应用程序。两者都导入到App.module.ts. 我正在使用 Nest 的Throttler Guard来保护整个应用程序。众所周知,GraphQL 不能与普通的 一起使用ThrottlerGuard,因此我创建了一个GqlThrottlerGuard并将其导入到 GraphQL 模块上,同时将原始的导入ThrottlerGuard到 REST 模块上。

所以,我的 graphQL 模块如下所示:

@Module({
  imports: [
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      autoSchemaFile: true
    }),
    ThrottlerModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        ttl: config.get('security.throttle.ttl'),
        limit: config.get('security.throttle.limit'),
      }),
    }),
  ],
  providers: [
    {
      provide: APP_GUARD,
      useClass: GqlThrottlerGuard,
    },
  ],
})
export class GraphModule { }
Run Code Online (Sandbox Code Playgroud)

还有 REST 模块,如下所示:

@Module({
  imports: [
    ThrottlerModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        ttl: config.get('security.throttle.ttl'),
        limit: config.get('security.throttle.limit'),
      }),
    }),
  ],
  controllers: [RestController],
  providers: [
    {
      provide: APP_GUARD,
      useClass: ThrottlerGuard,
    },
  ],
})
export class RestModule implements NestModule {}
Run Code Online (Sandbox Code Playgroud)

最后,这两个模块都导入到App Module中,这是我实际运行的模块:

@Module({
  imports: [
    RestModule,
    GraphModule,
  ],
})
export class AppModule { }
Run Code Online (Sandbox Code Playgroud)

由于某种原因,即使仅在 RestModule 上导入法线,这里看到的错误仍然发生在我身上。应该像这样工作吗?我该如何解决?GraphModuleThrottlerGuard

Jay*_*iel 5

APP_GUARD全局绑定,适用于所有路由。您应该创建一个连贯的防护,根据返回或ExecutionContext#getType返回的方法返回正确的请求响应httpgraphql

@Injectable()
export class CustomThrottlerGuard extends ThrottlerGuard {

  getRequestResponse(context: ExecutionContext) {
    const reqType = context.getType<ContextType | 'graphql'>()
    if (reqType === 'graphql') {
      const gqlCtx = GqlExecutionContext.create(context);
      const ctx = gqlCtx.getContext();
      return { req: ctx.req, res: ctx.res };
    } else if (reqType === 'http') {
      return {
        req: context.switchToHttp().getRequest(),
        res: context.switchToHttp().getResponse()
      }
    } else {
      // handle rpc and ws if you have them, otherwise ignore and make previous `else if` just an `else`
    }
  }
Run Code Online (Sandbox Code Playgroud)