throttler icon indicating copy to clipboard operation
throttler copied to clipboard

No documentation on how to use GqlThrottlerGuard with Subscription

Open vytautas-pranskunas- opened this issue 1 year ago • 8 comments

Is there an existing issue that is already proposing this?

  • [X] I have searched the existing issues

Is your feature request related to a problem? Please describe it

I am using global throttler guard for my graphql api. But I get an error when I am adding subscriptions "Cannot read properties of undefined (reading 'ip')", It is thrown bu GqlThrottlerGuard

Describe the solution you'd like

It would be great to have section in documentation here: https://docs.nestjs.com/security/rate-limiting#graphql how to handle it. I had to dig into your github code to see that there is a @SkipThrottle() decorator

Teachability, documentation, adoption, migration strategy

No response

What is the motivation / use case for changing the behavior?


vytautas-pranskunas- avatar Aug 18 '22 07:08 vytautas-pranskunas-

GraphQL Subscriptions, like general websockets, act a little bit differently. Can you get me a reproduction with subscriptions enabled and I can work on the documentation of how to make it work with the throttler?

jmcdo29 avatar Aug 18 '22 14:08 jmcdo29

@jmcdo29 it is just a matter of @SkipThrottle() - which I have found by diging into your repo code or you can make something else for people who wish to Throttle subscription messages :)

Unfurtunutelly i have no time at this moment f time to build repro code. But it is a matter of 1 resolver and GQL module from Nest.JS.

I can drop you some code that might speed your repro:

@Module({
    imports: [
        ThrottlerModule.forRoot({
            ttl: 60,
            limit: 60,
        }),
        GraphQLModule.forRootAsync<ApolloDriverConfig>({
            driver: ApolloDriver,
            useFactory: () => ({
                playground: false,
                autoSchemaFile: 'schema.gql',
                installSubscriptionHandlers: true,
                plugins: [ApolloServerPluginLandingPageLocalDefault()],
                subscriptions: {
                    'subscriptions-transport-ws': true
                    
                },
                formatError(error: GraphQLError) { return exceptionFormatter(error); },
                context: async ({ req, res }) => {

                    return {
                      
                    };
                },
            }),
        }),
        
    ],
    providers: [
       
        {
            provide: APP_GUARD,
            useExisting: GqlThrottlerGuard,
        },
      
        GqlThrottlerGuard,
        
    ]
})
export class AppModule {
   
}

and

@Public()
// @SkipThrottle()
@Resolver()
export class SubscriptionsResolver {
    constructor(@Inject('PUB_SUB') private pubSub: PubSub) { }

    @Subscription(() => NotificationResponse)
    notification(
        @Root() notificationPayload: NotificationPayload,
        @Args() args: NotificationsSubscriptionArgs,
    ) {
        return this.pubSub.asyncIterator(SubscriptionTopic.notifications);
    }
}

vytautas-pranskunas- avatar Aug 18 '22 15:08 vytautas-pranskunas-

I am running into a similar issue where all Query, Mutation operations are fine but the GqlThrottlerGuard throws Cannot read property 'header' of undefined error for GraphqQL subscription. Do I need to be doing something different? Or is skipping the only option at the moment?

aliabbasrizvi avatar Oct 26 '22 23:10 aliabbasrizvi

@aliabbasrizvi you'd need to find a reliable way to allow for writing headers of the websocket. The error comes from around here. If you can get a reproduction I can probably find something to use here

jmcdo29 avatar Oct 26 '22 23:10 jmcdo29