Skip to content

Commit ec16fd2

Browse files
Merge branch 'lukaszniemkiewicz-my-fix-branch'
2 parents ab68fc6 + a2aa4e8 commit ec16fd2

File tree

1 file changed

+51
-10
lines changed

1 file changed

+51
-10
lines changed

content/security/rate-limiting.md

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,41 @@ findAll() {
103103

104104
#### Proxies
105105

106-
If your application runs behind a proxy server, check the specific HTTP adapter options ([express](http://expressjs.com/en/guide/behind-proxies.html) and [fastify](https://www.fastify.io/docs/latest/Reference/Server/#trustproxy)) for the `trust proxy` option and enable it. Doing so will allow you to get the original IP address from the `X-Forwarded-For` header, and you can override the `getTracker()` method to pull the value from the header rather than from `req.ip`. The following example works with both express and fastify:
106+
If your application is running behind a proxy server, it’s essential to configure the HTTP adapter to trust the proxy. You can refer to the specific HTTP adapter options for [Express](http://expressjs.com/en/guide/behind-proxies.html) and [Fastify](https://www.fastify.io/docs/latest/Reference/Server/#trustproxy) to enable the `trust proxy` setting.
107+
108+
Here's an example that demonstrates how to enable `trust proxy` for the Express adapter:
107109

108110
```typescript
109-
// throttler-behind-proxy.guard.ts
111+
@@filename(main.ts)
112+
import { NestFactory } from '@nestjs/core';
113+
import { AppModule } from './app.module';
114+
import { NestExpressApplication } from '@nestjs/platform-express';
115+
116+
async function bootstrap() {
117+
const app = await NestFactory.create<NestExpressApplication>(AppModule);
118+
app.set('trust proxy', 'loopback'); // Trust requests from the loopback address
119+
await app.listen(3000);
120+
}
121+
122+
bootstrap();
123+
@@switch
124+
import { NestFactory } from '@nestjs/core';
125+
import { AppModule } from './app.module';
126+
import { NestExpressApplication } from '@nestjs/platform-express';
127+
128+
async function bootstrap() {
129+
const app = await NestFactory.create(AppModule);
130+
app.set('trust proxy', 'loopback'); // Trust requests from the loopback address
131+
await app.listen(3000);
132+
}
133+
134+
bootstrap();
135+
```
136+
137+
Enabling `trust proxy` allows you to retrieve the original IP address from the `X-Forwarded-For` header. You can also customize the behavior of your application by overriding the `getTracker()` method to extract the IP address from this header instead of relying on `req.ip`. The following example demonstrates how to achieve this for both Express and Fastify:
138+
139+
```typescript
140+
@@filename(throttler-behind-proxy.guard)
110141
import { ThrottlerGuard } from '@nestjs/throttler';
111142
import { Injectable } from '@nestjs/common';
112143

@@ -116,11 +147,6 @@ export class ThrottlerBehindProxyGuard extends ThrottlerGuard {
116147
return req.ips.length ? req.ips[0] : req.ip; // individualize IP extraction to meet your own needs
117148
}
118149
}
119-
120-
// app.controller.ts
121-
import { ThrottlerBehindProxyGuard } from './throttler-behind-proxy.guard';
122-
123-
@UseGuards(ThrottlerBehindProxyGuard)
124150
```
125151

126152
> info **Hint** You can find the API of the `req` Request object for express [here](https://expressjs.com/en/api.html#req.ips) and for fastify [here](https://www.fastify.io/docs/latest/Reference/Request/).
@@ -133,15 +159,30 @@ This module can work with websockets, but it requires some class extension. You
133159
@Injectable()
134160
export class WsThrottlerGuard extends ThrottlerGuard {
135161
async handleRequest(requestProps: ThrottlerRequest): Promise<boolean> {
136-
const { context, limit, ttl, throttler, blockDuration, getTracker, generateKey } = requestProps;
162+
const {
163+
context,
164+
limit,
165+
ttl,
166+
throttler,
167+
blockDuration,
168+
getTracker,
169+
generateKey,
170+
} = requestProps;
137171

138172
const client = context.switchToWs().getClient();
139173
const tracker = client._socket.remoteAddress;
140174
const key = generateKey(context, tracker, throttler.name);
141175
const { totalHits, timeToExpire, isBlocked, timeToBlockExpire } =
142-
await this.storageService.increment(key, ttl, limit, blockDuration, throttler.name);
176+
await this.storageService.increment(
177+
key,
178+
ttl,
179+
limit,
180+
blockDuration,
181+
throttler.name,
182+
);
143183

144-
const getThrottlerSuffix = (name: string) => (name === 'default' ? '' : `-${name}`);
184+
const getThrottlerSuffix = (name: string) =>
185+
name === 'default' ? '' : `-${name}`;
145186

146187
// Throw an error when the user reached their limit.
147188
if (isBlocked) {

0 commit comments

Comments
 (0)