express-rate-limit 6.0.3 → 6.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +52 -0
- package/dist/index.cjs +4 -5
- package/dist/index.d.ts +146 -48
- package/dist/index.mjs +3 -4
- package/package.json +17 -17
- package/readme.md +182 -217
- package/tsconfig.json +5 -7
package/changelog.md
CHANGED
|
@@ -6,6 +6,58 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
|
6
6
|
and this project adheres to
|
|
7
7
|
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
8
8
|
|
|
9
|
+
## [6.2.0](https://github.com/nfriedly/express-rate-limit/releases/tag/v6.2.0)
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Export the `MemoryStore`, so it can now be imported as a named import
|
|
14
|
+
(`import { MemoryStore } from 'express-rate-limit'`).
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Deprecate the `onLimitReached` option (this was supposed to be deprecated in
|
|
19
|
+
v6.0.0 itself); developers should use a custom handler function that checks if
|
|
20
|
+
the rate limit has been exceeded instead.
|
|
21
|
+
|
|
22
|
+
## [6.1.0](https://github.com/nfriedly/express-rate-limit/releases/tag/v6.1.0)
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- Added a named export `rateLimit` in case the default import does not work.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- Added a named export `default`, so Typescript CommonJS developers can
|
|
31
|
+
default-import the library (`import rateLimit from 'express-rate-limit'`).
|
|
32
|
+
|
|
33
|
+
## [6.0.5](https://github.com/nfriedly/express-rate-limit/releases/tag/v6.0.5)
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- Use named imports for ExpressJS types so users do not need to enable the
|
|
38
|
+
`esModuleInterop` flag in their Typescript compiler configuration.
|
|
39
|
+
|
|
40
|
+
## [6.0.4](https://github.com/nfriedly/express-rate-limit/releases/tag/v6.0.4)
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- Upload the built package as a `.tgz` to GitHub releases.
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
|
|
48
|
+
- Add ` main` and `module` fields to `package.json`. This helps tools such as
|
|
49
|
+
ESLint that do not yet support the `exports` field.
|
|
50
|
+
- Bumped the minimum node.js version in `package-lock.json` to match
|
|
51
|
+
`package.json`
|
|
52
|
+
|
|
53
|
+
## [6.0.3](https://github.com/nfriedly/express-rate-limit/releases/tag/v6.0.3)
|
|
54
|
+
|
|
55
|
+
### Changed
|
|
56
|
+
|
|
57
|
+
- Bumped minimum Node version from 12.9 to 14.5 in `package.json` because the
|
|
58
|
+
transpiled output uses the nullish coalescing operator (`??`), which
|
|
59
|
+
[isn't supported in node.js prior to 14.x](https://node.green/#ES2020-features--nullish-coalescing-operator-----).
|
|
60
|
+
|
|
9
61
|
## [6.0.2](https://github.com/nfriedly/express-rate-limit/releases/v6.0.2)
|
|
10
62
|
|
|
11
63
|
### Fixed
|
package/dist/index.cjs
CHANGED
|
@@ -24,7 +24,9 @@ var __toCommonJS = /* @__PURE__ */ ((cache) => {
|
|
|
24
24
|
// source/index.ts
|
|
25
25
|
var source_exports = {};
|
|
26
26
|
__export(source_exports, {
|
|
27
|
-
|
|
27
|
+
MemoryStore: () => MemoryStore,
|
|
28
|
+
default: () => lib_default,
|
|
29
|
+
rateLimit: () => lib_default
|
|
28
30
|
});
|
|
29
31
|
|
|
30
32
|
// source/memory-store.ts
|
|
@@ -219,8 +221,5 @@ var rateLimit = (passedOptions) => {
|
|
|
219
221
|
return middleware;
|
|
220
222
|
};
|
|
221
223
|
var lib_default = rateLimit;
|
|
222
|
-
|
|
223
|
-
// source/index.ts
|
|
224
|
-
var source_default = lib_default;
|
|
225
224
|
module.exports = __toCommonJS(source_exports);
|
|
226
|
-
module.exports = rateLimit;
|
|
225
|
+
module.exports = rateLimit; module.exports.default = rateLimit; module.exports.rateLimit = rateLimit; module.exports.MemoryStore = MemoryStore;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
// Generated by dts-bundle-generator v6.
|
|
1
|
+
// Generated by dts-bundle-generator v6.4.0
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { NextFunction, Request, RequestHandler, Response } from 'express';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Callback that fires when a client's hit counter is incremented.
|
|
7
7
|
*
|
|
8
|
-
* @param error {Error | undefined} - The error that occurred, if any
|
|
9
|
-
* @param totalHits {number} - The number of hits for that client so far
|
|
10
|
-
* @param resetTime {Date | undefined} - The time when the counter resets
|
|
8
|
+
* @param error {Error | undefined} - The error that occurred, if any.
|
|
9
|
+
* @param totalHits {number} - The number of hits for that client so far.
|
|
10
|
+
* @param resetTime {Date | undefined} - The time when the counter resets.
|
|
11
11
|
*/
|
|
12
12
|
export declare type IncrementCallback = (error: Error | undefined, totalHits: number, resetTime: Date | undefined) => void;
|
|
13
13
|
/**
|
|
14
14
|
* Method (in the form of middleware) to generate/retrieve a value based on the
|
|
15
|
-
* incoming request
|
|
15
|
+
* incoming request.
|
|
16
16
|
*
|
|
17
|
-
* @param request {
|
|
18
|
-
* @param response {
|
|
17
|
+
* @param request {Request} - The Express request object.
|
|
18
|
+
* @param response {Response} - The Express response object.
|
|
19
19
|
*
|
|
20
|
-
* @returns {T} - The value needed
|
|
20
|
+
* @returns {T} - The value needed.
|
|
21
21
|
*/
|
|
22
|
-
export declare type ValueDeterminingMiddleware<T> = (request:
|
|
22
|
+
export declare type ValueDeterminingMiddleware<T> = (request: Request, response: Response) => T | Promise<T>;
|
|
23
23
|
/**
|
|
24
24
|
* Express request handler that sends back a response when a client is
|
|
25
25
|
* rate-limited.
|
|
26
26
|
*
|
|
27
|
-
* @param request {
|
|
28
|
-
* @param response {
|
|
29
|
-
* @param next {
|
|
30
|
-
* @param optionsUsed {Options} - The options used to set up the middleware
|
|
27
|
+
* @param request {Request} - The Express request object.
|
|
28
|
+
* @param response {Response} - The Express response object.
|
|
29
|
+
* @param next {NextFunction} - The Express `next` function, can be called to skip responding.
|
|
30
|
+
* @param optionsUsed {Options} - The options used to set up the middleware.
|
|
31
31
|
*/
|
|
32
|
-
export declare type RateLimitExceededEventHandler = (request:
|
|
32
|
+
export declare type RateLimitExceededEventHandler = (request: Request, response: Response, next: NextFunction, optionsUsed: Options) => void;
|
|
33
33
|
/**
|
|
34
34
|
* Event callback that is triggered on a client's first request that exceeds the limit
|
|
35
35
|
* but not for subsequent requests. May be used for logging, etc. Should *not*
|
|
36
36
|
* send a response.
|
|
37
37
|
*
|
|
38
|
-
* @param request {
|
|
39
|
-
* @param response {
|
|
40
|
-
* @param optionsUsed {Options} - The options used to set up the middleware
|
|
38
|
+
* @param request {Request} - The Express request object.
|
|
39
|
+
* @param response {Response} - The Express response object.
|
|
40
|
+
* @param optionsUsed {Options} - The options used to set up the middleware.
|
|
41
41
|
*/
|
|
42
|
-
export declare type RateLimitReachedEventHandler = (request:
|
|
42
|
+
export declare type RateLimitReachedEventHandler = (request: Request, response: Response, optionsUsed: Options) => void;
|
|
43
43
|
/**
|
|
44
44
|
* Data returned from the `Store` when a client's hit counter is incremented.
|
|
45
45
|
*
|
|
46
|
-
* @property totalHits {number} - The number of hits for that client so far
|
|
47
|
-
* @property resetTime {Date | undefined} - The time when the counter resets
|
|
46
|
+
* @property totalHits {number} - The number of hits for that client so far.
|
|
47
|
+
* @property resetTime {Date | undefined} - The time when the counter resets.
|
|
48
48
|
*/
|
|
49
49
|
export declare type IncrementResponse = {
|
|
50
50
|
totalHits: number;
|
|
@@ -53,11 +53,11 @@ export declare type IncrementResponse = {
|
|
|
53
53
|
/**
|
|
54
54
|
* A modified Express request handler with the rate limit functions.
|
|
55
55
|
*/
|
|
56
|
-
export declare type RateLimitRequestHandler =
|
|
56
|
+
export declare type RateLimitRequestHandler = RequestHandler & {
|
|
57
57
|
/**
|
|
58
58
|
* Method to reset a client's hit counter.
|
|
59
59
|
*
|
|
60
|
-
* @param key {string} - The identifier for a client
|
|
60
|
+
* @param key {string} - The identifier for a client.
|
|
61
61
|
*/
|
|
62
62
|
resetKey: (key: string) => void;
|
|
63
63
|
};
|
|
@@ -70,20 +70,20 @@ export interface LegacyStore {
|
|
|
70
70
|
/**
|
|
71
71
|
* Method to increment a client's hit counter.
|
|
72
72
|
*
|
|
73
|
-
* @param key {string} - The identifier for a client
|
|
74
|
-
* @param callback {IncrementCallback} - The callback to call once the counter is incremented
|
|
73
|
+
* @param key {string} - The identifier for a client.
|
|
74
|
+
* @param callback {IncrementCallback} - The callback to call once the counter is incremented.
|
|
75
75
|
*/
|
|
76
76
|
incr: (key: string, callback: IncrementCallback) => void;
|
|
77
77
|
/**
|
|
78
78
|
* Method to decrement a client's hit counter.
|
|
79
79
|
*
|
|
80
|
-
* @param key {string} - The identifier for a client
|
|
80
|
+
* @param key {string} - The identifier for a client.
|
|
81
81
|
*/
|
|
82
82
|
decrement: (key: string) => void;
|
|
83
83
|
/**
|
|
84
84
|
* Method to reset a client's hit counter.
|
|
85
85
|
*
|
|
86
|
-
* @param key {string} - The identifier for a client
|
|
86
|
+
* @param key {string} - The identifier for a client.
|
|
87
87
|
*/
|
|
88
88
|
resetKey: (key: string) => void;
|
|
89
89
|
/**
|
|
@@ -99,27 +99,27 @@ export interface Store {
|
|
|
99
99
|
* Method that initializes the store, and has access to the options passed to
|
|
100
100
|
* the middleware too.
|
|
101
101
|
*
|
|
102
|
-
* @param options {Options} - The options used to setup the middleware
|
|
102
|
+
* @param options {Options} - The options used to setup the middleware.
|
|
103
103
|
*/
|
|
104
104
|
init?: (options: Options) => void;
|
|
105
105
|
/**
|
|
106
106
|
* Method to increment a client's hit counter.
|
|
107
107
|
*
|
|
108
|
-
* @param key {string} - The identifier for a client
|
|
108
|
+
* @param key {string} - The identifier for a client.
|
|
109
109
|
*
|
|
110
|
-
* @returns {IncrementResponse} - The number of hits and reset time for that client
|
|
110
|
+
* @returns {IncrementResponse} - The number of hits and reset time for that client.
|
|
111
111
|
*/
|
|
112
112
|
increment: (key: string) => Promise<IncrementResponse> | IncrementResponse;
|
|
113
113
|
/**
|
|
114
114
|
* Method to decrement a client's hit counter.
|
|
115
115
|
*
|
|
116
|
-
* @param key {string} - The identifier for a client
|
|
116
|
+
* @param key {string} - The identifier for a client.
|
|
117
117
|
*/
|
|
118
118
|
decrement: (key: string) => Promise<void> | void;
|
|
119
119
|
/**
|
|
120
120
|
* Method to reset a client's hit counter.
|
|
121
121
|
*
|
|
122
|
-
* @param key {string} - The identifier for a client
|
|
122
|
+
* @param key {string} - The identifier for a client.
|
|
123
123
|
*/
|
|
124
124
|
resetKey: (key: string) => Promise<void> | void;
|
|
125
125
|
/**
|
|
@@ -133,18 +133,24 @@ export interface Store {
|
|
|
133
133
|
export interface Options {
|
|
134
134
|
/**
|
|
135
135
|
* How long we should remember the requests.
|
|
136
|
+
*
|
|
137
|
+
* Defaults to `60000` ms (= 1 minute).
|
|
136
138
|
*/
|
|
137
139
|
readonly windowMs: number;
|
|
138
140
|
/**
|
|
139
|
-
* The maximum number of
|
|
141
|
+
* The maximum number of connections to allow during the `window` before
|
|
140
142
|
* rate limiting the client.
|
|
141
143
|
*
|
|
142
144
|
* Can be the limit itself as a number or express middleware that parses
|
|
143
145
|
* the request and then figures out the limit.
|
|
146
|
+
*
|
|
147
|
+
* Defaults to `5`.
|
|
144
148
|
*/
|
|
145
149
|
readonly max: number | ValueDeterminingMiddleware<number>;
|
|
146
150
|
/**
|
|
147
151
|
* The response body to send back when a client is rate limited.
|
|
152
|
+
*
|
|
153
|
+
* Defaults to `'Too many requests, please try again later.'`
|
|
148
154
|
*/
|
|
149
155
|
readonly message: any;
|
|
150
156
|
/**
|
|
@@ -156,10 +162,14 @@ export interface Options {
|
|
|
156
162
|
/**
|
|
157
163
|
* Whether to send `X-RateLimit-*` headers with the rate limit and the number
|
|
158
164
|
* of requests.
|
|
165
|
+
*
|
|
166
|
+
* Defaults to `true` (for backward compatibility).
|
|
159
167
|
*/
|
|
160
168
|
readonly legacyHeaders: boolean;
|
|
161
169
|
/**
|
|
162
|
-
* Whether to enable support for the rate limit
|
|
170
|
+
* Whether to enable support for the standardized rate limit headers (`RateLimit-*`).
|
|
171
|
+
*
|
|
172
|
+
* Defaults to `false` (for backward compatibility, but its use is recommended).
|
|
163
173
|
*/
|
|
164
174
|
readonly standardHeaders: boolean;
|
|
165
175
|
/**
|
|
@@ -171,41 +181,57 @@ export interface Options {
|
|
|
171
181
|
/**
|
|
172
182
|
* If `true`, the library will (by default) skip all requests that have a 4XX
|
|
173
183
|
* or 5XX status.
|
|
184
|
+
*
|
|
185
|
+
* Defaults to `false`.
|
|
174
186
|
*/
|
|
175
187
|
readonly skipFailedRequests: boolean;
|
|
176
188
|
/**
|
|
177
189
|
* If `true`, the library will (by default) skip all requests that have a
|
|
178
190
|
* status code less than 400.
|
|
191
|
+
*
|
|
192
|
+
* Defaults to `false`.
|
|
179
193
|
*/
|
|
180
194
|
readonly skipSuccessfulRequests: boolean;
|
|
181
|
-
/**
|
|
182
|
-
* Method to determine whether or not the request counts as 'succesful'. Used
|
|
183
|
-
* when either `skipSuccessfulRequests` or `skipFailedRequests` is set to true.
|
|
184
|
-
*/
|
|
185
|
-
readonly requestWasSuccessful: ValueDeterminingMiddleware<boolean>;
|
|
186
195
|
/**
|
|
187
196
|
* Method to generate custom identifiers for clients.
|
|
188
197
|
*
|
|
189
198
|
* By default, the client's IP address is used.
|
|
190
199
|
*/
|
|
191
200
|
readonly keyGenerator: ValueDeterminingMiddleware<string>;
|
|
192
|
-
/**
|
|
193
|
-
* Method (in the form of middleware) to determine whether or not this request
|
|
194
|
-
* counts towards a client's quota.
|
|
195
|
-
*/
|
|
196
|
-
readonly skip: ValueDeterminingMiddleware<boolean>;
|
|
197
201
|
/**
|
|
198
202
|
* Express request handler that sends back a response when a client is
|
|
199
203
|
* rate-limited.
|
|
204
|
+
*
|
|
205
|
+
* By default, sends back the `statusCode` and `message` set via the options.
|
|
200
206
|
*/
|
|
201
207
|
readonly handler: RateLimitExceededEventHandler;
|
|
202
208
|
/**
|
|
203
209
|
* Express request handler that sends back a response when a client has
|
|
204
210
|
* reached their rate limit, and will be rate limited on their next request.
|
|
211
|
+
*
|
|
212
|
+
* @deprecated 6.x - Please use a custom `handler` that checks the number of
|
|
213
|
+
* hits instead.
|
|
205
214
|
*/
|
|
206
215
|
readonly onLimitReached: RateLimitReachedEventHandler;
|
|
207
216
|
/**
|
|
208
|
-
*
|
|
217
|
+
* Method (in the form of middleware) to determine whether or not this request
|
|
218
|
+
* counts towards a client's quota.
|
|
219
|
+
*
|
|
220
|
+
* By default, skips no requests.
|
|
221
|
+
*/
|
|
222
|
+
readonly skip: ValueDeterminingMiddleware<boolean>;
|
|
223
|
+
/**
|
|
224
|
+
* Method to determine whether or not the request counts as 'succesful'. Used
|
|
225
|
+
* when either `skipSuccessfulRequests` or `skipFailedRequests` is set to true.
|
|
226
|
+
*
|
|
227
|
+
* By default, requests with a response status code less than 400 are considered
|
|
228
|
+
* successful.
|
|
229
|
+
*/
|
|
230
|
+
readonly requestWasSuccessful: ValueDeterminingMiddleware<boolean>;
|
|
231
|
+
/**
|
|
232
|
+
* The `Store` to use to store the hit count for each client.
|
|
233
|
+
*
|
|
234
|
+
* By default, the built-in `MemoryStore` will be used.
|
|
209
235
|
*/
|
|
210
236
|
store: Store;
|
|
211
237
|
/**
|
|
@@ -227,7 +253,7 @@ export interface Options {
|
|
|
227
253
|
* The extended request object that includes information about the client's
|
|
228
254
|
* rate limit.
|
|
229
255
|
*/
|
|
230
|
-
export declare type AugmentedRequest =
|
|
256
|
+
export declare type AugmentedRequest = Request & {
|
|
231
257
|
[key: string]: RateLimitInfo;
|
|
232
258
|
};
|
|
233
259
|
/**
|
|
@@ -240,9 +266,81 @@ export interface RateLimitInfo {
|
|
|
240
266
|
readonly remaining: number;
|
|
241
267
|
readonly resetTime: Date | undefined;
|
|
242
268
|
}
|
|
243
|
-
|
|
269
|
+
/**
|
|
270
|
+
*
|
|
271
|
+
* Create an instance of IP rate-limiting middleware for Express.
|
|
272
|
+
*
|
|
273
|
+
* @param passedOptions {Options} - Options to configure the rate limiter.
|
|
274
|
+
*
|
|
275
|
+
* @returns {RateLimitRequestHandler} - The middleware that rate-limits clients based on your configuration.
|
|
276
|
+
*
|
|
277
|
+
* @public
|
|
278
|
+
*/
|
|
279
|
+
export declare const rateLimit: (passedOptions?: (Omit<Partial<Options>, "store"> & {
|
|
244
280
|
store?: LegacyStore | Store | undefined;
|
|
245
281
|
}) | undefined) => RateLimitRequestHandler;
|
|
246
|
-
|
|
282
|
+
/**
|
|
283
|
+
* A `Store` that stores the hit count for each client in memory.
|
|
284
|
+
*
|
|
285
|
+
* @public
|
|
286
|
+
*/
|
|
287
|
+
export declare class MemoryStore implements Store {
|
|
288
|
+
/**
|
|
289
|
+
* The duration of time before which all hit counts are reset (in milliseconds).
|
|
290
|
+
*/
|
|
291
|
+
windowMs: number;
|
|
292
|
+
/**
|
|
293
|
+
* The map that stores the number of hits for each client in memory.
|
|
294
|
+
*/
|
|
295
|
+
hits: {
|
|
296
|
+
[key: string]: number | undefined;
|
|
297
|
+
};
|
|
298
|
+
/**
|
|
299
|
+
* The time at which all hit counts will be reset.
|
|
300
|
+
*/
|
|
301
|
+
resetTime: Date;
|
|
302
|
+
/**
|
|
303
|
+
* Method that initializes the store.
|
|
304
|
+
*
|
|
305
|
+
* @param options {Options} - The options used to setup the middleware.
|
|
306
|
+
*/
|
|
307
|
+
init(options: Options): void;
|
|
308
|
+
/**
|
|
309
|
+
* Method to increment a client's hit counter.
|
|
310
|
+
*
|
|
311
|
+
* @param key {string} - The identifier for a client.
|
|
312
|
+
*
|
|
313
|
+
* @returns {IncrementResponse} - The number of hits and reset time for that client.
|
|
314
|
+
*
|
|
315
|
+
* @public
|
|
316
|
+
*/
|
|
317
|
+
increment(key: string): Promise<IncrementResponse>;
|
|
318
|
+
/**
|
|
319
|
+
* Method to decrement a client's hit counter.
|
|
320
|
+
*
|
|
321
|
+
* @param key {string} - The identifier for a client.
|
|
322
|
+
*
|
|
323
|
+
* @public
|
|
324
|
+
*/
|
|
325
|
+
decrement(key: string): Promise<void>;
|
|
326
|
+
/**
|
|
327
|
+
* Method to reset a client's hit counter.
|
|
328
|
+
*
|
|
329
|
+
* @param key {string} - The identifier for a client.
|
|
330
|
+
*
|
|
331
|
+
* @public
|
|
332
|
+
*/
|
|
333
|
+
resetKey(key: string): Promise<void>;
|
|
334
|
+
/**
|
|
335
|
+
* Method to reset everyone's hit counter.
|
|
336
|
+
*
|
|
337
|
+
* @public
|
|
338
|
+
*/
|
|
339
|
+
resetAll(): Promise<void>;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export {
|
|
343
|
+
rateLimit as default,
|
|
344
|
+
};
|
|
247
345
|
|
|
248
346
|
export {};
|
package/dist/index.mjs
CHANGED
|
@@ -190,9 +190,8 @@ var rateLimit = (passedOptions) => {
|
|
|
190
190
|
return middleware;
|
|
191
191
|
};
|
|
192
192
|
var lib_default = rateLimit;
|
|
193
|
-
|
|
194
|
-
// source/index.ts
|
|
195
|
-
var source_default = lib_default;
|
|
196
193
|
export {
|
|
197
|
-
|
|
194
|
+
MemoryStore,
|
|
195
|
+
lib_default as default,
|
|
196
|
+
lib_default as rateLimit
|
|
198
197
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "express-rate-limit",
|
|
3
|
-
"version": "6.0
|
|
3
|
+
"version": "6.2.0",
|
|
4
4
|
"description": "Basic IP rate-limiting middleware for Express. Use to limit repeated requests to public APIs and/or endpoints such as password reset.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Nathan Friedly",
|
|
@@ -28,13 +28,15 @@
|
|
|
28
28
|
"attack"
|
|
29
29
|
],
|
|
30
30
|
"type": "module",
|
|
31
|
-
"types": "./dist/index.d.ts",
|
|
32
31
|
"exports": {
|
|
33
32
|
".": {
|
|
34
33
|
"import": "./dist/index.mjs",
|
|
35
34
|
"require": "./dist/index.cjs"
|
|
36
35
|
}
|
|
37
36
|
},
|
|
37
|
+
"main": "./dist/index.cjs",
|
|
38
|
+
"module": "./dist/index.mjs",
|
|
39
|
+
"types": "./dist/index.d.ts",
|
|
38
40
|
"files": [
|
|
39
41
|
"dist/",
|
|
40
42
|
"tsconfig.json",
|
|
@@ -48,7 +50,7 @@
|
|
|
48
50
|
},
|
|
49
51
|
"scripts": {
|
|
50
52
|
"clean": "del-cli dist/ coverage/ *.log *.tmp *.bak *.tgz",
|
|
51
|
-
"build:cjs": "esbuild --bundle --format=cjs --outfile=dist/index.cjs --footer:js=\"module.exports = rateLimit;\" source/index.ts",
|
|
53
|
+
"build:cjs": "esbuild --bundle --format=cjs --outfile=dist/index.cjs --footer:js=\"module.exports = rateLimit; module.exports.default = rateLimit; module.exports.rateLimit = rateLimit; module.exports.MemoryStore = MemoryStore;\" source/index.ts",
|
|
52
54
|
"build:esm": "esbuild --bundle --format=esm --outfile=dist/index.mjs source/index.ts",
|
|
53
55
|
"build:types": "dts-bundle-generator --out-file=dist/index.d.ts source/index.ts",
|
|
54
56
|
"compile": "run-s clean build:*",
|
|
@@ -60,7 +62,7 @@
|
|
|
60
62
|
"autofix": "run-s autofix:*",
|
|
61
63
|
"test:lib": "cross-env NODE_OPTIONS=--experimental-vm-modules jest",
|
|
62
64
|
"test:ext": "cd test/external/ && bash run-all-tests",
|
|
63
|
-
"test": "
|
|
65
|
+
"test": "run-s lint test:*",
|
|
64
66
|
"pre-commit": "lint-staged",
|
|
65
67
|
"prepare": "run-s compile && husky install config/husky"
|
|
66
68
|
},
|
|
@@ -68,24 +70,24 @@
|
|
|
68
70
|
"express": "^4"
|
|
69
71
|
},
|
|
70
72
|
"devDependencies": {
|
|
71
|
-
"@jest/globals": "^27.4.
|
|
73
|
+
"@jest/globals": "^27.4.6",
|
|
72
74
|
"@types/express": "^4.17.13",
|
|
73
|
-
"@types/jest": "^27.0
|
|
74
|
-
"@types/node": "^16.11.
|
|
75
|
+
"@types/jest": "^27.4.0",
|
|
76
|
+
"@types/node": "^16.11.21",
|
|
75
77
|
"@types/supertest": "^2.0.11",
|
|
76
78
|
"cross-env": "^7.0.3",
|
|
77
79
|
"del-cli": "^4.0.1",
|
|
78
|
-
"dts-bundle-generator": "^6.
|
|
79
|
-
"esbuild": "^0.14.
|
|
80
|
+
"dts-bundle-generator": "^6.4.0",
|
|
81
|
+
"esbuild": "^0.14.12",
|
|
80
82
|
"express": "^4.17.1",
|
|
81
83
|
"husky": "^7.0.4",
|
|
82
|
-
"jest": "^27.4.
|
|
83
|
-
"lint-staged": "^12.
|
|
84
|
+
"jest": "^27.4.7",
|
|
85
|
+
"lint-staged": "^12.2.2",
|
|
84
86
|
"npm-run-all": "^4.1.5",
|
|
85
|
-
"supertest": "^6.
|
|
86
|
-
"ts-jest": "^27.1.
|
|
87
|
+
"supertest": "^6.2.2",
|
|
88
|
+
"ts-jest": "^27.1.3",
|
|
87
89
|
"ts-node": "^10.4.0",
|
|
88
|
-
"typescript": "^4.5.
|
|
90
|
+
"typescript": "^4.5.5",
|
|
89
91
|
"xo": "^0.47.0"
|
|
90
92
|
},
|
|
91
93
|
"xo": {
|
|
@@ -97,9 +99,7 @@
|
|
|
97
99
|
"@typescript-eslint/consistent-indexed-object-style": [
|
|
98
100
|
"error",
|
|
99
101
|
"index-signature"
|
|
100
|
-
]
|
|
101
|
-
"import/no-named-as-default-member": 0,
|
|
102
|
-
"import/no-cycle": 0
|
|
102
|
+
]
|
|
103
103
|
}
|
|
104
104
|
},
|
|
105
105
|
"prettier": {
|
package/readme.md
CHANGED
|
@@ -22,11 +22,11 @@ This module was designed to only handle the basics and didn't even support
|
|
|
22
22
|
external stores initially. These other options all are excellent pieces of
|
|
23
23
|
software and may be more appropriate for some situations:
|
|
24
24
|
|
|
25
|
-
- [rate-limiter-flexible](https://www.npmjs.com/package/rate-limiter-flexible)
|
|
26
|
-
- [express-brute](https://www.npmjs.com/package/express-brute)
|
|
27
|
-
- [rate-limiter](https://www.npmjs.com/package/express-limiter)
|
|
25
|
+
- [`rate-limiter-flexible`](https://www.npmjs.com/package/rate-limiter-flexible)
|
|
26
|
+
- [`express-brute`](https://www.npmjs.com/package/express-brute)
|
|
27
|
+
- [`rate-limiter`](https://www.npmjs.com/package/express-limiter)
|
|
28
28
|
|
|
29
|
-
##
|
|
29
|
+
## Installation
|
|
30
30
|
|
|
31
31
|
From the npm registry:
|
|
32
32
|
|
|
@@ -51,14 +51,21 @@ Replace `{version}` with the version of the package that you want to your, e.g.:
|
|
|
51
51
|
|
|
52
52
|
## Usage
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
### Importing
|
|
55
|
+
|
|
56
|
+
This library is provided in ESM as well as CJS forms, and works with both
|
|
57
|
+
Javascript and Typescript projects.
|
|
58
|
+
|
|
59
|
+
**This package requires you to use Node 14 or above.**
|
|
60
|
+
|
|
61
|
+
Import it in a CommonJS project (`type: commonjs` or no `type` field in
|
|
62
|
+
`package.json`) as follows:
|
|
56
63
|
|
|
57
64
|
```ts
|
|
58
65
|
const rateLimit = require('express-rate-limit')
|
|
59
66
|
```
|
|
60
67
|
|
|
61
|
-
|
|
68
|
+
Import it in a ESM project (`type: module` in `package.json`) as follows:
|
|
62
69
|
|
|
63
70
|
```ts
|
|
64
71
|
import rateLimit from 'express-rate-limit'
|
|
@@ -132,8 +139,7 @@ app.post('/create-account', createAccountLimiter, (request, response) => {
|
|
|
132
139
|
To use a custom store:
|
|
133
140
|
|
|
134
141
|
```ts
|
|
135
|
-
import rateLimit from 'express-rate-limit'
|
|
136
|
-
import MemoryStore from 'express-rate-limit/memory-store.js'
|
|
142
|
+
import rateLimit, { MemoryStore } from 'express-rate-limit'
|
|
137
143
|
|
|
138
144
|
const apiLimiter = rateLimit({
|
|
139
145
|
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
@@ -182,64 +188,55 @@ it does.
|
|
|
182
188
|
For more information about the `trust proxy` setting, take a look at the
|
|
183
189
|
[official Express documentation](https://expressjs.com/en/guide/behind-proxies.html).
|
|
184
190
|
|
|
185
|
-
##
|
|
186
|
-
|
|
187
|
-
A `request.rateLimit` property is added to all requests with the `limit`,
|
|
188
|
-
`current`, and `remaining` number of requests and, if the store provides it, a
|
|
189
|
-
`resetTime` Date object. These may be used in your application code to take
|
|
190
|
-
additional actions or inform the user of their status.
|
|
191
|
-
|
|
192
|
-
The property name can be configured with the configuration option
|
|
193
|
-
`requestPropertyName`
|
|
194
|
-
|
|
195
|
-
## Configuration options
|
|
191
|
+
## Configuration
|
|
196
192
|
|
|
197
193
|
### `windowMs`
|
|
198
194
|
|
|
195
|
+
> `number`
|
|
196
|
+
|
|
199
197
|
Time frame for which requests are checked/remembered. Also used in the
|
|
200
198
|
`Retry-After` header when the limit is reached.
|
|
201
199
|
|
|
202
|
-
Note: with
|
|
203
|
-
|
|
204
|
-
|
|
200
|
+
Note: with stores that do not implement the `init` function (see the table in
|
|
201
|
+
the [`stores` section below](#stores)), you may need to configure this value
|
|
202
|
+
twice, once here and once on the store. In some cases the units also differ
|
|
203
|
+
(e.g. seconds vs miliseconds).
|
|
205
204
|
|
|
206
205
|
Defaults to `60000` ms (= 1 minute).
|
|
207
206
|
|
|
208
207
|
### `max`
|
|
209
208
|
|
|
210
|
-
|
|
211
|
-
response.
|
|
209
|
+
> `number | function`
|
|
212
210
|
|
|
213
|
-
|
|
214
|
-
|
|
211
|
+
The maximum number of connections to allow during the `window` before rate
|
|
212
|
+
limiting the client.
|
|
215
213
|
|
|
216
|
-
|
|
214
|
+
Can be the limit itself as a number or a (sync/async) function that accepts the
|
|
215
|
+
Express `request` and `response` objects and then returns a number.
|
|
217
216
|
|
|
218
|
-
|
|
217
|
+
Defaults to `5`. Set it to `0` to disable the rate limiter.
|
|
219
218
|
|
|
220
|
-
|
|
221
|
-
import rateLimit from 'express-rate-limit'
|
|
219
|
+
An example of using a function:
|
|
222
220
|
|
|
223
|
-
|
|
221
|
+
```ts
|
|
222
|
+
const isPremium = async (user) => {
|
|
224
223
|
// ...
|
|
225
224
|
}
|
|
226
225
|
|
|
227
226
|
const limiter = rateLimit({
|
|
228
|
-
//
|
|
229
|
-
max: (request, response) => {
|
|
230
|
-
if (isPremium(request)) return 10
|
|
227
|
+
// ...
|
|
228
|
+
max: async (request, response) => {
|
|
229
|
+
if (await isPremium(request.user)) return 10
|
|
231
230
|
else return 5
|
|
232
231
|
},
|
|
233
|
-
// ...
|
|
234
232
|
})
|
|
235
|
-
|
|
236
|
-
// Apply the rate limiting middleware to all requests
|
|
237
|
-
app.use(limiter)
|
|
238
233
|
```
|
|
239
234
|
|
|
240
235
|
### `message`
|
|
241
236
|
|
|
242
|
-
|
|
237
|
+
> `any`
|
|
238
|
+
|
|
239
|
+
The response body to send back when a client is rate limited.
|
|
243
240
|
|
|
244
241
|
May be a `string`, JSON object, or any other value that Express's
|
|
245
242
|
[response.send](https://expressjs.com/en/4x/api.html#response.send) method
|
|
@@ -249,240 +246,208 @@ Defaults to `'Too many requests, please try again later.'`
|
|
|
249
246
|
|
|
250
247
|
### `statusCode`
|
|
251
248
|
|
|
252
|
-
|
|
249
|
+
> `number`
|
|
253
250
|
|
|
254
|
-
|
|
251
|
+
The HTTP status code to send back when a client is rate limited.
|
|
252
|
+
|
|
253
|
+
Defaults to `429` (HTTP 429 Too Many Requests - RFC 6585).
|
|
255
254
|
|
|
256
255
|
### `legacyHeaders`
|
|
257
256
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
257
|
+
> `boolean`
|
|
258
|
+
|
|
259
|
+
Whether to send the legacy rate limit headers for the limit
|
|
260
|
+
(`X-RateLimit-Limit`), current usage (`X-RateLimit-Remaining`) and reset time
|
|
261
|
+
(if the store provides it) (`X-RateLimit-Reset`) on all responses. If set to
|
|
262
|
+
`true`, the middleware also sends the `Retry-After` header on all blocked
|
|
263
|
+
requests.
|
|
261
264
|
|
|
262
|
-
Defaults to `true
|
|
265
|
+
Defaults to `true` (for backward compatibility).
|
|
263
266
|
|
|
264
267
|
> Renamed in `6.x` from `headers` to `legacyHeaders`.
|
|
265
268
|
|
|
266
269
|
### `standardHeaders`
|
|
267
270
|
|
|
268
|
-
|
|
269
|
-
[ratelimit standardization draft](https://github.com/ietf-wg-httpapi/ratelimit-headers/blob/main/draft-ietf-httpapi-ratelimit-headers.md)
|
|
270
|
-
adopted by the IETF: `RateLimit-Limit`, `RateLimit-Remaining`, and, if the store
|
|
271
|
-
supports it, `RateLimit-Reset`. May be used in conjunction with, or instead of
|
|
272
|
-
the `legacyHeaders` option.
|
|
271
|
+
> `boolean`
|
|
273
272
|
|
|
274
|
-
|
|
273
|
+
Whether to enable support for headers conforming to the
|
|
274
|
+
[ratelimit standardization draft](https://github.com/ietf-wg-httpapi/ratelimit-headers/blob/main/draft-ietf-httpapi-ratelimit-headers.md)
|
|
275
|
+
adopted by the IETF (`RateLimit-Limit`, `RateLimit-Remaining`, and, if the store
|
|
276
|
+
supports it, `RateLimit-Reset`). If set to `true`, the middleware also sends the
|
|
277
|
+
`Retry-After` header on all blocked requests. May be used in conjunction with,
|
|
278
|
+
or instead of the `legacyHeaders` option.
|
|
275
279
|
|
|
276
|
-
Defaults to `false` (for backward compatibility
|
|
280
|
+
Defaults to `false` (for backward compatibility, but its use is recommended).
|
|
277
281
|
|
|
278
282
|
> Renamed in `6.x` from `draft_polli_ratelimit_headers` to `standardHeaders`.
|
|
279
283
|
|
|
280
|
-
### `
|
|
284
|
+
### `requestPropertyName`
|
|
281
285
|
|
|
282
|
-
|
|
286
|
+
> `string`
|
|
283
287
|
|
|
284
|
-
|
|
288
|
+
The name of the property on the Express `request` object to store the rate limit
|
|
289
|
+
info.
|
|
285
290
|
|
|
286
|
-
|
|
287
|
-
const keyGenerator = (request /*, response*/) => request.ip
|
|
288
|
-
```
|
|
291
|
+
Defaults to `'rateLimit'`.
|
|
289
292
|
|
|
290
|
-
### `
|
|
293
|
+
### `skipFailedRequests`
|
|
294
|
+
|
|
295
|
+
> `boolean`
|
|
296
|
+
|
|
297
|
+
When set to `true`, failed requests won't be counted. Request considered failed
|
|
298
|
+
when the `requestWasSuccessful` option returns `false`. By default, this means
|
|
299
|
+
requests fail when:
|
|
300
|
+
|
|
301
|
+
- the response status >= 400
|
|
302
|
+
- the request was cancelled before last chunk of data was sent (response `close`
|
|
303
|
+
event triggered)
|
|
304
|
+
- the response `error` event was triggered by response
|
|
305
|
+
|
|
306
|
+
(Technically they are counted and then un-counted, so a large number of slow
|
|
307
|
+
requests all at once could still trigger a rate-limit. This may be fixed in a
|
|
308
|
+
future release. PRs welcome!)
|
|
309
|
+
|
|
310
|
+
Defaults to `false`.
|
|
311
|
+
|
|
312
|
+
### `skipSuccessfulRequests`
|
|
313
|
+
|
|
314
|
+
> `boolean`
|
|
315
|
+
|
|
316
|
+
If `true`, the library will (by default) skip all requests that are considered
|
|
317
|
+
'failed' by the `requestWasSuccessful` function. By default, this means requests
|
|
318
|
+
succeed when the response status code < 400.
|
|
291
319
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
320
|
+
(Technically they are counted and then un-counted, so a large number of slow
|
|
321
|
+
requests all at once could still trigger a rate-limit. This may be fixed in a
|
|
322
|
+
future release. PRs welcome!)
|
|
323
|
+
|
|
324
|
+
Defaults to `false`.
|
|
325
|
+
|
|
326
|
+
### `keyGenerator`
|
|
297
327
|
|
|
298
|
-
|
|
299
|
-
requests and, if the store provides it, a `resetTime` Date object.
|
|
328
|
+
> `function`
|
|
300
329
|
|
|
301
|
-
|
|
330
|
+
Method to generate custom identifiers for clients.
|
|
331
|
+
|
|
332
|
+
Should be a (sync/async) function that accepts the Express `request` and
|
|
333
|
+
`response` objects and then returns a string.
|
|
334
|
+
|
|
335
|
+
By default, the client's IP address is used:
|
|
302
336
|
|
|
303
337
|
```ts
|
|
304
|
-
const
|
|
305
|
-
|
|
306
|
-
|
|
338
|
+
const limiter = rateLimit({
|
|
339
|
+
// ...
|
|
340
|
+
keyGenerator: (request, response) => request.ip,
|
|
341
|
+
})
|
|
307
342
|
```
|
|
308
343
|
|
|
309
|
-
### `
|
|
344
|
+
### `handler`
|
|
345
|
+
|
|
346
|
+
> `function`
|
|
310
347
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
service sends out a 200 status code on errors.
|
|
348
|
+
Express request handler that sends back a response when a client is
|
|
349
|
+
rate-limited.
|
|
314
350
|
|
|
315
|
-
|
|
351
|
+
By default, sends back the `statusCode` and `message` set via the options:
|
|
316
352
|
|
|
317
353
|
```ts
|
|
318
|
-
const
|
|
354
|
+
const limiter = rateLimit({
|
|
355
|
+
// ...
|
|
356
|
+
handler: (request, response, next, options) =>
|
|
357
|
+
response.status(options.statusCode).send(options.message),
|
|
358
|
+
})
|
|
319
359
|
```
|
|
320
360
|
|
|
321
|
-
### `
|
|
361
|
+
### `onLimitReached`
|
|
322
362
|
|
|
323
|
-
|
|
324
|
-
when:
|
|
363
|
+
> `function`
|
|
325
364
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
- response `error` event was triggered by response
|
|
365
|
+
A (sync/async) function that accepts the Express `request` and `response`
|
|
366
|
+
objects that is called when a client has reached their rate limit, and will be
|
|
367
|
+
rate limited on their next request.
|
|
330
368
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
369
|
+
This method was
|
|
370
|
+
[deprecated in v6](https://github.com/nfriedly/express-rate-limit/releases/v6.0.0) -
|
|
371
|
+
Please use a custom `handler` that checks the number of hits instead.
|
|
334
372
|
|
|
335
|
-
|
|
373
|
+
### `skip`
|
|
336
374
|
|
|
337
|
-
|
|
375
|
+
> `function`
|
|
338
376
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
future release.)
|
|
377
|
+
Function to determine whether or not this request counts towards a client's
|
|
378
|
+
quota. Should be a (sync/async) function that accepts the Express `request` and
|
|
379
|
+
`response` objects and then returns `true` or `false`.
|
|
343
380
|
|
|
344
|
-
|
|
381
|
+
Could also act as an allowlist for certain keys:
|
|
345
382
|
|
|
346
|
-
|
|
383
|
+
```ts
|
|
384
|
+
const allowlist = ['192.168.0.56', '192.168.0.21']
|
|
347
385
|
|
|
348
|
-
|
|
349
|
-
|
|
386
|
+
const limiter = rateLimit({
|
|
387
|
+
// ...
|
|
388
|
+
skip: (request, response) => allowlist.includes(request.ip),
|
|
389
|
+
})
|
|
390
|
+
```
|
|
350
391
|
|
|
351
|
-
|
|
392
|
+
By default, it skips no requests:
|
|
352
393
|
|
|
353
394
|
```ts
|
|
354
|
-
const
|
|
395
|
+
const limiter = rateLimit({
|
|
396
|
+
// ...
|
|
397
|
+
skip: (request, response) => false,
|
|
398
|
+
})
|
|
355
399
|
```
|
|
356
400
|
|
|
357
|
-
### `
|
|
401
|
+
### `requestWasSuccessful`
|
|
358
402
|
|
|
359
|
-
|
|
360
|
-
`request` object.
|
|
403
|
+
> `function`
|
|
361
404
|
|
|
362
|
-
|
|
405
|
+
Method to determine whether or not the request counts as 'succesful'. Used when
|
|
406
|
+
either `skipSuccessfulRequests` or `skipFailedRequests` is set to true. Should
|
|
407
|
+
be a (sync/async) function that accepts the Express `request` and `response`
|
|
408
|
+
objects and then returns `true` or `false`.
|
|
409
|
+
|
|
410
|
+
By default, requests with a response status code less than 400 are considered
|
|
411
|
+
successful:
|
|
412
|
+
|
|
413
|
+
```ts
|
|
414
|
+
const limiter = rateLimit({
|
|
415
|
+
// ...
|
|
416
|
+
requestWasSuccessful: (request, response) => response.statusCode < 400,
|
|
417
|
+
})
|
|
418
|
+
```
|
|
363
419
|
|
|
364
420
|
### `store`
|
|
365
421
|
|
|
366
|
-
|
|
422
|
+
> `Store`
|
|
367
423
|
|
|
368
|
-
|
|
424
|
+
The `Store` to use to store the hit count for each client.
|
|
369
425
|
|
|
370
|
-
|
|
426
|
+
By default, the [`memory-store`](source/memory-store.ts) is used.
|
|
371
427
|
|
|
372
|
-
|
|
373
|
-
Does not share state when app has multiple processes or servers.
|
|
374
|
-
- [rate-limit-redis](https://npmjs.com/package/rate-limit-redis): A
|
|
375
|
-
[Redis](http://redis.io/)-backed store, more suitable for large or demanding
|
|
376
|
-
deployments.
|
|
377
|
-
- [rate-limit-memcached](https://npmjs.org/package/rate-limit-memcached): A
|
|
378
|
-
[Memcached](https://memcached.org/)-backed store.
|
|
379
|
-
- [rate-limit-mongo](https://www.npmjs.com/package/rate-limit-mongo): A
|
|
380
|
-
[MongoDB](https://www.mongodb.com/)-backed store.
|
|
381
|
-
- [precise-memory-rate-limit](https://www.npmjs.com/package/precise-memory-rate-limit) -
|
|
382
|
-
A memory store similar to the built-in one, except that it stores a distinct
|
|
383
|
-
timestamp for each IP rather than bucketing them together.
|
|
428
|
+
Here is a list of external stores:
|
|
384
429
|
|
|
385
|
-
|
|
386
|
-
|
|
430
|
+
| Name | Description | Legacy/Modern |
|
|
431
|
+
| -------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------- |
|
|
432
|
+
| [`memory-store`](source/memory-store.ts) | _(default)_ Simple in-memory option. Does not share state when app has multiple processes or servers. | Modern as of v6.0.0 |
|
|
433
|
+
| [`rate-limit-redis`](https://npmjs.com/package/rate-limit-redis) | A [Redis](http://redis.io/)-backed store, more suitable for large or demanding deployments. | Modern as of v3.0.0 |
|
|
434
|
+
| [`rate-limit-memcached`](https://npmjs.org/package/rate-limit-memcached) | A [Memcached](https://memcached.org/)-backed store. | Legacy |
|
|
435
|
+
| [`rate-limit-mongo`](https://www.npmjs.com/package/rate-limit-mongo) | A [MongoDB](https://www.mongodb.com/)-backed store. | Legacy |
|
|
436
|
+
| [`precise-memory-rate-limit`](https://www.npmjs.com/package/precise-memory-rate-limit) | A memory store similar to the built-in one, except that it stores a distinct timestamp for each key. | Legacy |
|
|
387
437
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
Options,
|
|
392
|
-
IncrementResponse,
|
|
393
|
-
} from 'express-rate-limit'
|
|
394
|
-
|
|
395
|
-
/**
|
|
396
|
-
* A {@link Store} that stores the hit count for each client.
|
|
397
|
-
*
|
|
398
|
-
* @public
|
|
399
|
-
*/
|
|
400
|
-
class SomeStore implements Store {
|
|
401
|
-
/**
|
|
402
|
-
* Some store-specific parameter.
|
|
403
|
-
*/
|
|
404
|
-
customParam!: string
|
|
405
|
-
/**
|
|
406
|
-
* The duration of time before which all hit counts are reset (in milliseconds).
|
|
407
|
-
*/
|
|
408
|
-
windowMs!: number
|
|
409
|
-
|
|
410
|
-
/**
|
|
411
|
-
* @constructor for {@link SomeStore}. Only required if the user needs to pass
|
|
412
|
-
* some store specific parameters. For example, in a Mongo Store, the user will
|
|
413
|
-
* need to pass the URI, username and password for the Mongo database.
|
|
414
|
-
*
|
|
415
|
-
* @param customParam {string} - Some store-specific parameter.
|
|
416
|
-
*/
|
|
417
|
-
constructor(customParam: string) {
|
|
418
|
-
this.customParam = customParam
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
/**
|
|
422
|
-
* Method that actually initializes the store. Must be synchronous.
|
|
423
|
-
*
|
|
424
|
-
* @param options {Options} - The options used to setup the middleware.
|
|
425
|
-
*
|
|
426
|
-
* @public
|
|
427
|
-
*/
|
|
428
|
-
init(options: Options): void {
|
|
429
|
-
this.windowMs = options.windowMs
|
|
430
|
-
|
|
431
|
-
// ...
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
/**
|
|
435
|
-
* Method to increment a client's hit counter.
|
|
436
|
-
*
|
|
437
|
-
* @param key {string} - The identifier for a client
|
|
438
|
-
*
|
|
439
|
-
* @returns {IncrementResponse} - The number of hits and reset time for that client
|
|
440
|
-
*
|
|
441
|
-
* @public
|
|
442
|
-
*/
|
|
443
|
-
async increment(key: string): Promise<IncrementResponse> {
|
|
444
|
-
// ...
|
|
445
|
-
|
|
446
|
-
return {
|
|
447
|
-
totalHits,
|
|
448
|
-
resetTime,
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
/**
|
|
453
|
-
* Method to decrement a client's hit counter.
|
|
454
|
-
*
|
|
455
|
-
* @param key {string} - The identifier for a client
|
|
456
|
-
*
|
|
457
|
-
* @public
|
|
458
|
-
*/
|
|
459
|
-
async decrement(key: string): Promise<void> {
|
|
460
|
-
// ...
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
/**
|
|
464
|
-
* Method to reset a client's hit counter.
|
|
465
|
-
*
|
|
466
|
-
* @param key {string} - The identifier for a client
|
|
467
|
-
*
|
|
468
|
-
* @public
|
|
469
|
-
*/
|
|
470
|
-
async resetKey(key: string): Promise<void> {
|
|
471
|
-
// ...
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
* Method to reset everyone's hit counter.
|
|
476
|
-
*
|
|
477
|
-
* @public
|
|
478
|
-
*/
|
|
479
|
-
async resetAll(): Promise<void> {
|
|
480
|
-
// ...
|
|
481
|
-
}
|
|
482
|
-
}
|
|
438
|
+
Take a look at
|
|
439
|
+
[this guide](https://github.com/nfriedly/express-rate-limit/wiki/Creating-Your-Own-Store)
|
|
440
|
+
if you wish to create your own store.
|
|
483
441
|
|
|
484
|
-
|
|
485
|
-
|
|
442
|
+
## Request API
|
|
443
|
+
|
|
444
|
+
A `request.rateLimit` property is added to all requests with the `limit`,
|
|
445
|
+
`current`, and `remaining` number of requests and, if the store provides it, a
|
|
446
|
+
`resetTime` Date object. These may be used in your application code to take
|
|
447
|
+
additional actions or inform the user of their status.
|
|
448
|
+
|
|
449
|
+
The property name can be configured with the configuration option
|
|
450
|
+
`requestPropertyName`.
|
|
486
451
|
|
|
487
452
|
## Instance API
|
|
488
453
|
|
package/tsconfig.json
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
{
|
|
2
|
+
"include": ["source/"],
|
|
3
|
+
"exclude": ["node_modules/"],
|
|
2
4
|
"compilerOptions": {
|
|
3
5
|
"declaration": true,
|
|
4
|
-
|
|
5
6
|
"strict": true,
|
|
6
7
|
"noUnusedLocals": true,
|
|
7
8
|
"noImplicitReturns": true,
|
|
8
9
|
"noFallthroughCasesInSwitch": true,
|
|
9
|
-
|
|
10
|
-
"moduleResolution": "node"
|
|
11
|
-
|
|
12
|
-
},
|
|
13
|
-
"include": ["./source/**/*.ts"],
|
|
14
|
-
"exclude": ["./node_modules"]
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"moduleResolution": "node"
|
|
12
|
+
}
|
|
15
13
|
}
|