Skip to content

Commit aff6ed0

Browse files
committed
feat(back): provide custom request throttler tracker and trust proxy IP
1 parent 0a6f3a3 commit aff6ed0

4 files changed

Lines changed: 28 additions & 9 deletions

File tree

apps/backend/src/app/app.module.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { Module } from '@nestjs/common';
2-
import { APP_FILTER, APP_GUARD } from '@nestjs/core';
2+
import { APP_FILTER } from '@nestjs/core';
33
import { LoggerModule, Params as PinoParams } from 'nestjs-pino';
44
import pino from 'pino';
55
import { ConfigModule, ConfigService } from '@nestjs/config';
6-
import { ThrottlerGuard, ThrottlerModule, seconds } from '@nestjs/throttler';
6+
import { ThrottlerModule, seconds } from '@nestjs/throttler';
77
import { SentryModule } from '@sentry/nestjs/setup';
88
import { ScheduleModule } from '@nestjs/schedule';
99
import * as Sentry from '@sentry/node';
@@ -186,10 +186,6 @@ import { ValkeyModule } from './modules/valkey/valkey.module';
186186
{
187187
provide: APP_FILTER,
188188
useClass: ExceptionHandlerFilter
189-
},
190-
{
191-
provide: APP_GUARD,
192-
useClass: ThrottlerGuard
193189
}
194190
]
195191
})

apps/backend/src/app/modules/auth/auth.module.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { JwtGuard } from './jwt/jwt.guard';
1010
import { JwtAuthService } from './jwt/jwt-auth.service';
1111
import { SteamOpenIDService } from './steam/steam-openid.service';
1212
import { LimitedGuard } from './limited.guard';
13+
import { UserIPThrottlerGuard } from './user-ip-throttler.guard';
1314

1415
@Module({
1516
imports: [
@@ -35,6 +36,12 @@ import { LimitedGuard } from './limited.guard';
3536
provide: APP_GUARD,
3637
useClass: LimitedGuard
3738
},
39+
{
40+
// Provide throttler guard here instread of the app module
41+
// so that it runs after the request user is set
42+
provide: APP_GUARD,
43+
useClass: UserIPThrottlerGuard
44+
},
3845
JwtAuthService,
3946
SteamOpenIDService
4047
]
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { ThrottlerGuard } from '@nestjs/throttler';
2+
import { Injectable } from '@nestjs/common';
3+
import { FastifyRequest } from 'fastify';
4+
5+
@Injectable()
6+
export class UserIPThrottlerGuard extends ThrottlerGuard {
7+
protected async getTracker(req: FastifyRequest): Promise<string> {
8+
const ip = req.ips.length > 0 ? req.ips[0] : req.ip;
9+
const uid = req.user?.id ?? -1;
10+
11+
return `${uid}@${ip}`;
12+
}
13+
}

apps/backend/src/main.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import cors from '@fastify/cors';
1717
import multipart from '@fastify/multipart';
1818
import { Logger } from 'nestjs-pino';
1919
import cluster from 'node:cluster';
20-
import { Environment } from './app/config';
20+
import { Config, Environment } from './app/config';
2121
import { AppModule } from './app/app.module';
2222
import { VALIDATION_PIPE_CONFIG } from './app/dto';
2323
import { FIRST_WORKER_ENV_VAR } from './clustered';
@@ -30,9 +30,13 @@ async function bootstrap() {
3030
return this.toString();
3131
};
3232

33+
const env: Environment = Config.env;
34+
3335
const app = await NestFactory.create<NestFastifyApplication>(
3436
AppModule,
35-
new FastifyAdapter(),
37+
new FastifyAdapter({
38+
trustProxy: env === Environment.PRODUCTION
39+
}),
3640
{
3741
bufferLogs: true, // Buffer logs until Pino is attached
3842
rawBody: true // So we can use RawBodyRequest
@@ -43,7 +47,6 @@ async function bootstrap() {
4347
app.useLogger(app.get(Logger));
4448

4549
const configService = app.get(ConfigService);
46-
const env: Environment = configService.getOrThrow('env');
4750

4851
// Steam game auth and replay submission from game send raw octet-streams.
4952
// Steam auth we could limit to 2kb, but replays can be massive. Limiting

0 commit comments

Comments
 (0)