#Socker IO Rate limit with Nest js

19 messages · Page 1 of 1 (latest)

last imp
#

Hello I am new in nest js i am trying to set rate limit in my nest js project for socket.io and i want to use it at global levele means it should be used by all my socket gateway files i used throttle but it is not working me at all please help me if anyone know the solution please help me if you want more details then let me know

violet sigil
#

Hi @last imp , can you please provide some minimal code. At least there will be something to check, otherwise, it's just guessing.

last imp
#

ok let me send you

#

import { Module } from '@nestjs/common';
import { AppEnvModule } from './app-env';
import { ServiceHandlerModule } from './service-handler';
import { RedisModule } from '@nestjs-modules/ioredis';
import { ThrottlerModule,ThrottlerGuard } from '@nestjs/throttler';

import { APP_GUARD } from '@nestjs/core';
import { HttpThrottlerGuard } from './http-throttler.guard';
import { ThrottlerStorageRedisService } from 'nestjs-throttler-storage-redis';
import { BaseSocketGateway } from './base-socket.gateway';

@Module({
imports: [
RedisModule.forRoot({
type: 'single',
url: process.env.REDIS_URL,
}),
ThrottlerModule.forRoot({
storage: new ThrottlerStorageRedisService(), // Use Redis storage
throttlers: [
// HTTP API rate limiting (applied via HttpThrottlerGuard)
{
name: 'http-api',
ttl: 60,
limit: 100, // Adjust HTTP limits as needed
blockDuration: 300
},
// Socket.IO rate limiting (applied via SocketThrottlerGuard)
{
name: 'socket-io',
ttl: 60000,
limit: 10,
blockDuration: 300
}
]
}),
AppEnvModule,
ServiceHandlerModule
],
controllers: [],
providers: [{
provide: APP_GUARD,
useClass: ThrottlerGuard, // Applies only to HTTP
},
BaseSocketGateway
],
})
export class AppModule {}

app.module.ts

==============

#

import { Injectable, ExecutionContext } from '@nestjs/common';
import { ThrottlerGuard,ThrottlerRequest } from '@nestjs/throttler';
import { WsException } from '@nestjs/websockets';

@Injectable()
export class WsThrottlerGuard extends ThrottlerGuard {
async handleRequest(
requestProps: ThrottlerRequest
): Promise<boolean> {

const { context, limit, ttl, throttler } = requestProps;
const client = context.switchToWs().getClient();
const ip = client.handshake.address; // Or use another method to get the client's identifier
console.log("Limit called")
const key = this.generateKey(context, ip, ttl.toString());
const { totalHits } = await this.storageService.increment( key,
  ttl,
  limit,
  Number(throttler.blockDuration),
'socket-io');

if (totalHits > limit) {
  throw new WsException('Too Many Requests');
}

return true;

}
}

this is my guard socker guard

#

in my gateway i using guard like this

#

if you want more resource let me know i will send

violet sigil
#

And by not working you mean...

last imp
#

i checked it via grafana tool i have set limit only 10 for sockets event listing but in grafana i am emiting more than 10 events still it is listing whole sockets event properly just example let suppose i have set limit 10 if i emit 15 socket events it must me listen 10 socket events remaining must be failed that i actually want

violet sigil
#

Do you see this message in your logs console.log("Limit called")
And do they match your expectations?

last imp
#

this log is not being printed out

#

this class's functionality is not being called

violet sigil
#

Have you registered all of your guards in providers?

last imp
#

@Module({
imports: [
RedisModule.forRoot({
type: 'single',
url: process.env.REDIS_URL,
}),
ThrottlerModule.forRoot({
storage: new ThrottlerStorageRedisService(), // Use Redis storage
throttlers: [
// HTTP API rate limiting (applied via HttpThrottlerGuard)
{
name: 'http-api',
ttl: 60,
limit: 100, // Adjust HTTP limits as needed
blockDuration: 300
},
// Socket.IO rate limiting (applied via SocketThrottlerGuard)
{
name: 'socket-io',
ttl: 60000,
limit: 10,
blockDuration: 300
}
]
}),
AppEnvModule,
ServiceHandlerModule
],
controllers: [],
providers: [{
provide: APP_GUARD,
useClass: ThrottlerGuard,
},
BaseSocketGateway
],
})

yes here this is my app.moduel.ts ThrottlerGuard i applied and also i registered my socket gateway file which is BaseSocketGateway

blazing daggerBOT
#

Please format your question or answer with Markdown formatting.
It leads to better readability and an easier time to spot problems.
For code blocks, you can wrap your block with three back ticks before and after the block, and after the first three back ticks you can add a language (like ts) to add syntax highlighting.

```ts
@Injectable()
export class MySuperAwesomeService {

constructor(@Inject('InjectionToken') private readonly dep: SomeDependency) {}

getRandomNumber(): number {
return Math.round(Math.random() * 1000);
}
}
```

That ☝️, becomes this 👇

@Injectable()
export class MySuperAwesomeService {

  constructor(@Inject('InjectionToken') private readonly dep: SomeDependency) {}

  getRandomNumber(): number {
    return Math.round(Math.random() * 1000);
  }
}
violet sigil
#

I can’t see your WsThrottleGuard to be registered anywhere

last imp
#

okay please let me know the steps to register it ?

violet sigil
#

Sorry, I’ve reread the docs and they are confusing as hell

There's a few things to keep in mind when working with WebSockets:

Guard cannot be registered with the APP_GUARD or app.useGlobalGuards()
When a limit is reached, Nest will emit an exception event, so make sure there is a listener ready for this

https://docs.nestjs.com/security/rate-limiting
it doesn’t answer your question though

violet sigil
#

Can it be your generateKey function is wrong?
https://github.com/nestjs/throttler/blob/3d1ecee2bfb4f1b55f49580108194a586b4ceac1/src/throttler-module-options.interface.ts#L137
It should take throttler name as last parameter, not other value.
The same can be true for increment function
Try using throttler.name instead

GitHub

A rate limiting module for NestJS to work with Fastify, Express, GQL, Websockets, and RPC 🧭 - nestjs/throttler