user2167582
user2167582

Reputation: 6378

Cannot read property 'ip' of undefined when testing rate limiting on nest.js

So I have the following configured in my nest.js graphql applicaiton, which seems to be working;

@Module({
  imports: [
    ThrottlerModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        ttl: config.get('THROTTLE_TTL'),
        limit: config.get('THROTTLE_LIMIT'),
      }),
    }),
  ],
  providers: [
    {
      provide: APP_GUARD,
      useClass: ThrottlerGuard,
    },
  ],
})
export class AppModule {}

but when I try to load test against my local server, the dropped requests all raise the following error

[Nest] 3177  - 2022-09-18T16:25:36.188Z   ERROR [ExceptionsHandler] Cannot read property 'ip' of undefined
TypeError: Cannot read property 'ip' of undefined

Why is the request handler not able to capture IP address? Is it b/c its going through one localhost to another?

Upvotes: 1

Views: 1628

Answers (2)

To handle both Graphql and http requests

import { ExecutionContext, Injectable } from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';
import {ThrottlerGuard} from '@nestjs/throttler';

@Injectable()
export class CustomThrottlerGuard extends ThrottlerGuard {
 getRequestResponse(context: ExecutionContext) {
   if (context.getType() === 'http') {
     const ctx = context.switchToHttp();
     return {req: ctx.getRequest(), res: ctx.getResponse() };
   }
   const gqlCtx = GqlExecutionContext.create(context);
   const ctx = gqlCtx.getContext();
   return {req: ctx.req, res: ctx.res };
 }
}

Upvotes: 1

Jay McDoniel
Jay McDoniel

Reputation: 70412

As the documentation shows the ThrottlerGuard needs to be extended to make the getRequestResponse method return the correct values so that the ip and headers objects can be referenced properly.

@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 };
  }
}

Upvotes: 2

Related Questions