GqlThrottlerGuard (for a particular resolver)
import { Injectable, ExecutionContext } from '@nestjs/common';
import { ThrottlerGuard } from '@nestjs/throttler';
import { GqlExecutionContext } from '@nestjs/graphql';
import { GraphQLResolveInfo } from 'graphql';
@Injectable()
export class GqlThrottlerGuard extends ThrottlerGuard {
getRequestResponse(context: ExecutionContext) {
const gqlCtx = GqlExecutionContext.create(context);
const ctx = gqlCtx.getContext();
return { req: ctx.req, res: ctx.res };
}
async handleRequest(
context: ExecutionContext,
limit: number,
ttl: number,
): Promise<boolean> {
const gqlCtx = GqlExecutionContext.create(context);
const info = gqlCtx.getInfo<GraphQLResolveInfo>();
const operationName = info.operation.name?.value;
const queriesToThrottle = ['HighlyExpensiveQuery', 'AnotherSlowQuery'];
if (operationName && queriesToThrottle.includes(operationName)) {
const httpContext = context.switchToHttp();
const request = httpContext.getRequest();
const tracker = this.getTracker(request);
const key = this.generateKey(context, tracker, limit, ttl);
const { totalHits } = await this.storageService.increment(key, ttl);
if (totalHits > limit) {
this.throwThrottlingException(context);
}
return true;
}
return true;
}
}