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
#Socker IO Rate limit with Nest js
19 messages · Page 1 of 1 (latest)
Hi @last imp , can you please provide some minimal code. At least there will be something to check, otherwise, it's just guessing.
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
And by not working you mean...
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
Do you see this message in your logs console.log("Limit called")
And do they match your expectations?
Have you registered all of your guards in providers?
@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
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);
}
}
I can’t see your WsThrottleGuard to be registered anywhere
okay please let me know the steps to register it ?
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
Documentation | NestJS - A progressive Node.js framework
Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming).
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