express-rate-limit 6.7.0 → 6.7.2
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 +20 -4
- package/dist/index.cjs +73 -4
- package/dist/index.d.cts +359 -0
- package/dist/index.d.mts +359 -0
- package/dist/index.d.ts +11 -11
- package/dist/index.mjs +75 -4
- package/package.json +25 -20
- package/readme.md +6 -1
package/changelog.md
CHANGED
|
@@ -6,15 +6,31 @@ 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.7.1](https://github.com/express-rate-limit/express-rate-limit/releases/tag/v6.7.1)
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Fixed compatibility with TypeScript's TypeScript new `node16` module
|
|
14
|
+
resolution strategy (See
|
|
15
|
+
[#355](https://github.com/express-rate-limit/express-rate-limit/issues/355))
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Bumped development dependencies.
|
|
20
|
+
- Added `node` 20 to list of versions the CI jobs run on.
|
|
21
|
+
|
|
22
|
+
No functional changes.
|
|
23
|
+
|
|
9
24
|
## [6.7.0](https://github.com/express-rate-limit/express-rate-limit/releases/tag/v6.7.0)
|
|
10
25
|
|
|
11
26
|
### Changed
|
|
12
27
|
|
|
13
|
-
- Updated links to point to new express-rate-limit organization on GitHub.
|
|
14
|
-
- Added advertisement to
|
|
28
|
+
- Updated links to point to the new `express-rate-limit` organization on GitHub.
|
|
29
|
+
- Added advertisement to `readme.md` for project sponsor
|
|
15
30
|
[Zuplo](https://zuplo.link/express-rate-limit).
|
|
16
|
-
- Updated
|
|
17
|
-
-
|
|
31
|
+
- Updated to `typescript` version 5 and bumped other dependencies.
|
|
32
|
+
- Dropped `node` 12, and added `node` 19 to the list of versions the CI jobs run
|
|
33
|
+
on.
|
|
18
34
|
|
|
19
35
|
No functional changes.
|
|
20
36
|
|
package/dist/index.cjs
CHANGED
|
@@ -3,6 +3,7 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
7
|
var __export = (target, all) => {
|
|
7
8
|
for (var name in all)
|
|
8
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -16,6 +17,10 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
17
|
return to;
|
|
17
18
|
};
|
|
18
19
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
var __publicField = (obj, key, value) => {
|
|
21
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
22
|
+
return value;
|
|
23
|
+
};
|
|
19
24
|
|
|
20
25
|
// source/index.ts
|
|
21
26
|
var source_exports = {};
|
|
@@ -28,11 +33,34 @@ module.exports = __toCommonJS(source_exports);
|
|
|
28
33
|
|
|
29
34
|
// source/memory-store.ts
|
|
30
35
|
var calculateNextResetTime = (windowMs) => {
|
|
31
|
-
const resetTime = new Date();
|
|
36
|
+
const resetTime = /* @__PURE__ */ new Date();
|
|
32
37
|
resetTime.setMilliseconds(resetTime.getMilliseconds() + windowMs);
|
|
33
38
|
return resetTime;
|
|
34
39
|
};
|
|
35
40
|
var MemoryStore = class {
|
|
41
|
+
constructor() {
|
|
42
|
+
/**
|
|
43
|
+
* The duration of time before which all hit counts are reset (in milliseconds).
|
|
44
|
+
*/
|
|
45
|
+
__publicField(this, "windowMs");
|
|
46
|
+
/**
|
|
47
|
+
* The map that stores the number of hits for each client in memory.
|
|
48
|
+
*/
|
|
49
|
+
__publicField(this, "hits");
|
|
50
|
+
/**
|
|
51
|
+
* The time at which all hit counts will be reset.
|
|
52
|
+
*/
|
|
53
|
+
__publicField(this, "resetTime");
|
|
54
|
+
/**
|
|
55
|
+
* Reference to the active timer.
|
|
56
|
+
*/
|
|
57
|
+
__publicField(this, "interval");
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Method that initializes the store.
|
|
61
|
+
*
|
|
62
|
+
* @param options {Options} - The options used to setup the middleware.
|
|
63
|
+
*/
|
|
36
64
|
init(options) {
|
|
37
65
|
this.windowMs = options.windowMs;
|
|
38
66
|
this.resetTime = calculateNextResetTime(this.windowMs);
|
|
@@ -43,6 +71,15 @@ var MemoryStore = class {
|
|
|
43
71
|
if (this.interval.unref)
|
|
44
72
|
this.interval.unref();
|
|
45
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Method to increment a client's hit counter.
|
|
76
|
+
*
|
|
77
|
+
* @param key {string} - The identifier for a client.
|
|
78
|
+
*
|
|
79
|
+
* @returns {IncrementResponse} - The number of hits and reset time for that client.
|
|
80
|
+
*
|
|
81
|
+
* @public
|
|
82
|
+
*/
|
|
46
83
|
async increment(key) {
|
|
47
84
|
var _a;
|
|
48
85
|
const totalHits = ((_a = this.hits[key]) != null ? _a : 0) + 1;
|
|
@@ -52,25 +89,54 @@ var MemoryStore = class {
|
|
|
52
89
|
resetTime: this.resetTime
|
|
53
90
|
};
|
|
54
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Method to decrement a client's hit counter.
|
|
94
|
+
*
|
|
95
|
+
* @param key {string} - The identifier for a client.
|
|
96
|
+
*
|
|
97
|
+
* @public
|
|
98
|
+
*/
|
|
55
99
|
async decrement(key) {
|
|
56
100
|
const current = this.hits[key];
|
|
57
101
|
if (current)
|
|
58
102
|
this.hits[key] = current - 1;
|
|
59
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Method to reset a client's hit counter.
|
|
106
|
+
*
|
|
107
|
+
* @param key {string} - The identifier for a client.
|
|
108
|
+
*
|
|
109
|
+
* @public
|
|
110
|
+
*/
|
|
60
111
|
async resetKey(key) {
|
|
61
112
|
delete this.hits[key];
|
|
62
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Method to reset everyone's hit counter.
|
|
116
|
+
*
|
|
117
|
+
* @public
|
|
118
|
+
*/
|
|
63
119
|
async resetAll() {
|
|
64
120
|
this.hits = {};
|
|
65
121
|
this.resetTime = calculateNextResetTime(this.windowMs);
|
|
66
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Method to stop the timer (if currently running) and prevent any memory
|
|
125
|
+
* leaks.
|
|
126
|
+
*
|
|
127
|
+
* @public
|
|
128
|
+
*/
|
|
67
129
|
shutdown() {
|
|
68
130
|
clearInterval(this.interval);
|
|
69
131
|
}
|
|
70
132
|
};
|
|
71
133
|
|
|
72
134
|
// source/lib.ts
|
|
73
|
-
var isLegacyStore = (store) =>
|
|
135
|
+
var isLegacyStore = (store) => (
|
|
136
|
+
// Check that `incr` exists but `increment` does not - store authors might want
|
|
137
|
+
// to keep both around for backwards compatibility.
|
|
138
|
+
typeof store.incr === "function" && typeof store.increment !== "function"
|
|
139
|
+
);
|
|
74
140
|
var promisifyStore = (passedStore) => {
|
|
75
141
|
if (!isLegacyStore(passedStore)) {
|
|
76
142
|
return passedStore;
|
|
@@ -137,10 +203,13 @@ var parseOptions = (passedOptions) => {
|
|
|
137
203
|
},
|
|
138
204
|
onLimitReached(_request, _response, _optionsUsed) {
|
|
139
205
|
},
|
|
206
|
+
// Allow the options object to be overriden by the options passed to the middleware.
|
|
140
207
|
...notUndefinedOptions,
|
|
208
|
+
// Note that this field is declared after the user's options are spread in,
|
|
209
|
+
// so that this field doesn't get overriden with an un-promisified store!
|
|
141
210
|
store: promisifyStore((_c = notUndefinedOptions.store) != null ? _c : new MemoryStore())
|
|
142
211
|
};
|
|
143
|
-
if (typeof config.store.increment !== "function" || typeof config.store.decrement !== "function" || typeof config.store.resetKey !== "function" ||
|
|
212
|
+
if (typeof config.store.increment !== "function" || typeof config.store.decrement !== "function" || typeof config.store.resetKey !== "function" || config.store.resetAll !== void 0 && typeof config.store.resetAll !== "function" || config.store.init !== void 0 && typeof config.store.init !== "function") {
|
|
144
213
|
throw new TypeError(
|
|
145
214
|
"An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface."
|
|
146
215
|
);
|
|
@@ -183,7 +252,7 @@ var rateLimit = (passedOptions) => {
|
|
|
183
252
|
augmentedRequest[options.requestPropertyName].remaining
|
|
184
253
|
);
|
|
185
254
|
if (resetTime instanceof Date) {
|
|
186
|
-
response.setHeader("Date", new Date().toUTCString());
|
|
255
|
+
response.setHeader("Date", (/* @__PURE__ */ new Date()).toUTCString());
|
|
187
256
|
response.setHeader(
|
|
188
257
|
"X-RateLimit-Reset",
|
|
189
258
|
Math.ceil(resetTime.getTime() / 1e3)
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
// Generated by dts-bundle-generator v7.0.0
|
|
2
|
+
|
|
3
|
+
import { NextFunction, Request, RequestHandler, Response } from 'express';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Callback that fires when a client's hit counter is incremented.
|
|
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.
|
|
11
|
+
*/
|
|
12
|
+
export type IncrementCallback = (error: Error | undefined, totalHits: number, resetTime: Date | undefined) => void;
|
|
13
|
+
/**
|
|
14
|
+
* Method (in the form of middleware) to generate/retrieve a value based on the
|
|
15
|
+
* incoming request.
|
|
16
|
+
*
|
|
17
|
+
* @param request {Request} - The Express request object.
|
|
18
|
+
* @param response {Response} - The Express response object.
|
|
19
|
+
*
|
|
20
|
+
* @returns {T} - The value needed.
|
|
21
|
+
*/
|
|
22
|
+
export type ValueDeterminingMiddleware<T> = (request: Request, response: Response) => T | Promise<T>;
|
|
23
|
+
/**
|
|
24
|
+
* Express request handler that sends back a response when a client is
|
|
25
|
+
* rate-limited.
|
|
26
|
+
*
|
|
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
|
+
*/
|
|
32
|
+
export type RateLimitExceededEventHandler = (request: Request, response: Response, next: NextFunction, optionsUsed: Options) => void;
|
|
33
|
+
/**
|
|
34
|
+
* Event callback that is triggered on a client's first request that exceeds the limit
|
|
35
|
+
* but not for subsequent requests. May be used for logging, etc. Should *not*
|
|
36
|
+
* send a response.
|
|
37
|
+
*
|
|
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
|
+
*/
|
|
42
|
+
export type RateLimitReachedEventHandler = (request: Request, response: Response, optionsUsed: Options) => void;
|
|
43
|
+
/**
|
|
44
|
+
* Data returned from the `Store` when a client's hit counter is incremented.
|
|
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.
|
|
48
|
+
*/
|
|
49
|
+
export type IncrementResponse = {
|
|
50
|
+
totalHits: number;
|
|
51
|
+
resetTime: Date | undefined;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* A modified Express request handler with the rate limit functions.
|
|
55
|
+
*/
|
|
56
|
+
export type RateLimitRequestHandler = RequestHandler & {
|
|
57
|
+
/**
|
|
58
|
+
* Method to reset a client's hit counter.
|
|
59
|
+
*
|
|
60
|
+
* @param key {string} - The identifier for a client.
|
|
61
|
+
*/
|
|
62
|
+
resetKey: (key: string) => void;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* An interface that all hit counter stores must implement.
|
|
66
|
+
*
|
|
67
|
+
* @deprecated 6.x - Implement the `Store` interface instead.
|
|
68
|
+
*/
|
|
69
|
+
export type LegacyStore = {
|
|
70
|
+
/**
|
|
71
|
+
* Method to increment a client's hit counter.
|
|
72
|
+
*
|
|
73
|
+
* @param key {string} - The identifier for a client.
|
|
74
|
+
* @param callback {IncrementCallback} - The callback to call once the counter is incremented.
|
|
75
|
+
*/
|
|
76
|
+
incr: (key: string, callback: IncrementCallback) => void;
|
|
77
|
+
/**
|
|
78
|
+
* Method to decrement a client's hit counter.
|
|
79
|
+
*
|
|
80
|
+
* @param key {string} - The identifier for a client.
|
|
81
|
+
*/
|
|
82
|
+
decrement: (key: string) => void;
|
|
83
|
+
/**
|
|
84
|
+
* Method to reset a client's hit counter.
|
|
85
|
+
*
|
|
86
|
+
* @param key {string} - The identifier for a client.
|
|
87
|
+
*/
|
|
88
|
+
resetKey: (key: string) => void;
|
|
89
|
+
/**
|
|
90
|
+
* Method to reset everyone's hit counter.
|
|
91
|
+
*/
|
|
92
|
+
resetAll?: () => void;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* An interface that all hit counter stores must implement.
|
|
96
|
+
*/
|
|
97
|
+
export type Store = {
|
|
98
|
+
/**
|
|
99
|
+
* Method that initializes the store, and has access to the options passed to
|
|
100
|
+
* the middleware too.
|
|
101
|
+
*
|
|
102
|
+
* @param options {Options} - The options used to setup the middleware.
|
|
103
|
+
*/
|
|
104
|
+
init?: (options: Options) => void;
|
|
105
|
+
/**
|
|
106
|
+
* Method to increment a client's hit counter.
|
|
107
|
+
*
|
|
108
|
+
* @param key {string} - The identifier for a client.
|
|
109
|
+
*
|
|
110
|
+
* @returns {IncrementResponse} - The number of hits and reset time for that client.
|
|
111
|
+
*/
|
|
112
|
+
increment: (key: string) => Promise<IncrementResponse> | IncrementResponse;
|
|
113
|
+
/**
|
|
114
|
+
* Method to decrement a client's hit counter.
|
|
115
|
+
*
|
|
116
|
+
* @param key {string} - The identifier for a client.
|
|
117
|
+
*/
|
|
118
|
+
decrement: (key: string) => Promise<void> | void;
|
|
119
|
+
/**
|
|
120
|
+
* Method to reset a client's hit counter.
|
|
121
|
+
*
|
|
122
|
+
* @param key {string} - The identifier for a client.
|
|
123
|
+
*/
|
|
124
|
+
resetKey: (key: string) => Promise<void> | void;
|
|
125
|
+
/**
|
|
126
|
+
* Method to reset everyone's hit counter.
|
|
127
|
+
*/
|
|
128
|
+
resetAll?: () => Promise<void> | void;
|
|
129
|
+
/**
|
|
130
|
+
* Method to shutdown the store, stop timers, and release all resources.
|
|
131
|
+
*/
|
|
132
|
+
shutdown?: () => Promise<void> | void;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* The configuration options for the rate limiter.
|
|
136
|
+
*/
|
|
137
|
+
export type Options = {
|
|
138
|
+
/**
|
|
139
|
+
* How long we should remember the requests.
|
|
140
|
+
*
|
|
141
|
+
* Defaults to `60000` ms (= 1 minute).
|
|
142
|
+
*/
|
|
143
|
+
readonly windowMs: number;
|
|
144
|
+
/**
|
|
145
|
+
* The maximum number of connections to allow during the `window` before
|
|
146
|
+
* rate limiting the client.
|
|
147
|
+
*
|
|
148
|
+
* Can be the limit itself as a number or express middleware that parses
|
|
149
|
+
* the request and then figures out the limit.
|
|
150
|
+
*
|
|
151
|
+
* Defaults to `5`.
|
|
152
|
+
*/
|
|
153
|
+
readonly max: number | ValueDeterminingMiddleware<number>;
|
|
154
|
+
/**
|
|
155
|
+
* The response body to send back when a client is rate limited.
|
|
156
|
+
*
|
|
157
|
+
* Defaults to `'Too many requests, please try again later.'`
|
|
158
|
+
*/
|
|
159
|
+
readonly message: any | ValueDeterminingMiddleware<any>;
|
|
160
|
+
/**
|
|
161
|
+
* The HTTP status code to send back when a client is rate limited.
|
|
162
|
+
*
|
|
163
|
+
* Defaults to `HTTP 429 Too Many Requests` (RFC 6585).
|
|
164
|
+
*/
|
|
165
|
+
readonly statusCode: number;
|
|
166
|
+
/**
|
|
167
|
+
* Whether to send `X-RateLimit-*` headers with the rate limit and the number
|
|
168
|
+
* of requests.
|
|
169
|
+
*
|
|
170
|
+
* Defaults to `true` (for backward compatibility).
|
|
171
|
+
*/
|
|
172
|
+
readonly legacyHeaders: boolean;
|
|
173
|
+
/**
|
|
174
|
+
* Whether to enable support for the standardized rate limit headers (`RateLimit-*`).
|
|
175
|
+
*
|
|
176
|
+
* Defaults to `false` (for backward compatibility, but its use is recommended).
|
|
177
|
+
*/
|
|
178
|
+
readonly standardHeaders: boolean;
|
|
179
|
+
/**
|
|
180
|
+
* The name of the property on the request object to store the rate limit info.
|
|
181
|
+
*
|
|
182
|
+
* Defaults to `rateLimit`.
|
|
183
|
+
*/
|
|
184
|
+
readonly requestPropertyName: string;
|
|
185
|
+
/**
|
|
186
|
+
* If `true`, the library will (by default) skip all requests that have a 4XX
|
|
187
|
+
* or 5XX status.
|
|
188
|
+
*
|
|
189
|
+
* Defaults to `false`.
|
|
190
|
+
*/
|
|
191
|
+
readonly skipFailedRequests: boolean;
|
|
192
|
+
/**
|
|
193
|
+
* If `true`, the library will (by default) skip all requests that have a
|
|
194
|
+
* status code less than 400.
|
|
195
|
+
*
|
|
196
|
+
* Defaults to `false`.
|
|
197
|
+
*/
|
|
198
|
+
readonly skipSuccessfulRequests: boolean;
|
|
199
|
+
/**
|
|
200
|
+
* Method to generate custom identifiers for clients.
|
|
201
|
+
*
|
|
202
|
+
* By default, the client's IP address is used.
|
|
203
|
+
*/
|
|
204
|
+
readonly keyGenerator: ValueDeterminingMiddleware<string>;
|
|
205
|
+
/**
|
|
206
|
+
* Express request handler that sends back a response when a client is
|
|
207
|
+
* rate-limited.
|
|
208
|
+
*
|
|
209
|
+
* By default, sends back the `statusCode` and `message` set via the options.
|
|
210
|
+
*/
|
|
211
|
+
readonly handler: RateLimitExceededEventHandler;
|
|
212
|
+
/**
|
|
213
|
+
* Express request handler that sends back a response when a client has
|
|
214
|
+
* reached their rate limit, and will be rate limited on their next request.
|
|
215
|
+
*
|
|
216
|
+
* @deprecated 6.x - Please use a custom `handler` that checks the number of
|
|
217
|
+
* hits instead.
|
|
218
|
+
*/
|
|
219
|
+
readonly onLimitReached: RateLimitReachedEventHandler;
|
|
220
|
+
/**
|
|
221
|
+
* Method (in the form of middleware) to determine whether or not this request
|
|
222
|
+
* counts towards a client's quota.
|
|
223
|
+
*
|
|
224
|
+
* By default, skips no requests.
|
|
225
|
+
*/
|
|
226
|
+
readonly skip: ValueDeterminingMiddleware<boolean>;
|
|
227
|
+
/**
|
|
228
|
+
* Method to determine whether or not the request counts as 'succesful'. Used
|
|
229
|
+
* when either `skipSuccessfulRequests` or `skipFailedRequests` is set to true.
|
|
230
|
+
*
|
|
231
|
+
* By default, requests with a response status code less than 400 are considered
|
|
232
|
+
* successful.
|
|
233
|
+
*/
|
|
234
|
+
readonly requestWasSuccessful: ValueDeterminingMiddleware<boolean>;
|
|
235
|
+
/**
|
|
236
|
+
* The `Store` to use to store the hit count for each client.
|
|
237
|
+
*
|
|
238
|
+
* By default, the built-in `MemoryStore` will be used.
|
|
239
|
+
*/
|
|
240
|
+
store: Store | LegacyStore;
|
|
241
|
+
/**
|
|
242
|
+
* Whether to send `X-RateLimit-*` headers with the rate limit and the number
|
|
243
|
+
* of requests.
|
|
244
|
+
*
|
|
245
|
+
* @deprecated 6.x - This option was renamed to `legacyHeaders`.
|
|
246
|
+
*/
|
|
247
|
+
headers?: boolean;
|
|
248
|
+
/**
|
|
249
|
+
* Whether to send `RateLimit-*` headers with the rate limit and the number
|
|
250
|
+
* of requests.
|
|
251
|
+
*
|
|
252
|
+
* @deprecated 6.x - This option was renamed to `standardHeaders`.
|
|
253
|
+
*/
|
|
254
|
+
draft_polli_ratelimit_headers?: boolean;
|
|
255
|
+
};
|
|
256
|
+
/**
|
|
257
|
+
* The extended request object that includes information about the client's
|
|
258
|
+
* rate limit.
|
|
259
|
+
*/
|
|
260
|
+
export type AugmentedRequest = Request & {
|
|
261
|
+
[key: string]: RateLimitInfo;
|
|
262
|
+
};
|
|
263
|
+
/**
|
|
264
|
+
* The rate limit related information for each client included in the
|
|
265
|
+
* Express request object.
|
|
266
|
+
*/
|
|
267
|
+
export type RateLimitInfo = {
|
|
268
|
+
readonly limit: number;
|
|
269
|
+
readonly current: number;
|
|
270
|
+
readonly remaining: number;
|
|
271
|
+
readonly resetTime: Date | undefined;
|
|
272
|
+
};
|
|
273
|
+
/**
|
|
274
|
+
*
|
|
275
|
+
* Create an instance of IP rate-limiting middleware for Express.
|
|
276
|
+
*
|
|
277
|
+
* @param passedOptions {Options} - Options to configure the rate limiter.
|
|
278
|
+
*
|
|
279
|
+
* @returns {RateLimitRequestHandler} - The middleware that rate-limits clients based on your configuration.
|
|
280
|
+
*
|
|
281
|
+
* @public
|
|
282
|
+
*/
|
|
283
|
+
export declare const rateLimit: (passedOptions?: Partial<Options>) => RateLimitRequestHandler;
|
|
284
|
+
/**
|
|
285
|
+
* A `Store` that stores the hit count for each client in memory.
|
|
286
|
+
*
|
|
287
|
+
* @public
|
|
288
|
+
*/
|
|
289
|
+
export declare class MemoryStore implements Store {
|
|
290
|
+
/**
|
|
291
|
+
* The duration of time before which all hit counts are reset (in milliseconds).
|
|
292
|
+
*/
|
|
293
|
+
windowMs: number;
|
|
294
|
+
/**
|
|
295
|
+
* The map that stores the number of hits for each client in memory.
|
|
296
|
+
*/
|
|
297
|
+
hits: {
|
|
298
|
+
[key: string]: number | undefined;
|
|
299
|
+
};
|
|
300
|
+
/**
|
|
301
|
+
* The time at which all hit counts will be reset.
|
|
302
|
+
*/
|
|
303
|
+
resetTime: Date;
|
|
304
|
+
/**
|
|
305
|
+
* Reference to the active timer.
|
|
306
|
+
*/
|
|
307
|
+
interval?: NodeJS.Timer;
|
|
308
|
+
/**
|
|
309
|
+
* Method that initializes the store.
|
|
310
|
+
*
|
|
311
|
+
* @param options {Options} - The options used to setup the middleware.
|
|
312
|
+
*/
|
|
313
|
+
init(options: Options): void;
|
|
314
|
+
/**
|
|
315
|
+
* Method to increment a client's hit counter.
|
|
316
|
+
*
|
|
317
|
+
* @param key {string} - The identifier for a client.
|
|
318
|
+
*
|
|
319
|
+
* @returns {IncrementResponse} - The number of hits and reset time for that client.
|
|
320
|
+
*
|
|
321
|
+
* @public
|
|
322
|
+
*/
|
|
323
|
+
increment(key: string): Promise<IncrementResponse>;
|
|
324
|
+
/**
|
|
325
|
+
* Method to decrement a client's hit counter.
|
|
326
|
+
*
|
|
327
|
+
* @param key {string} - The identifier for a client.
|
|
328
|
+
*
|
|
329
|
+
* @public
|
|
330
|
+
*/
|
|
331
|
+
decrement(key: string): Promise<void>;
|
|
332
|
+
/**
|
|
333
|
+
* Method to reset a client's hit counter.
|
|
334
|
+
*
|
|
335
|
+
* @param key {string} - The identifier for a client.
|
|
336
|
+
*
|
|
337
|
+
* @public
|
|
338
|
+
*/
|
|
339
|
+
resetKey(key: string): Promise<void>;
|
|
340
|
+
/**
|
|
341
|
+
* Method to reset everyone's hit counter.
|
|
342
|
+
*
|
|
343
|
+
* @public
|
|
344
|
+
*/
|
|
345
|
+
resetAll(): Promise<void>;
|
|
346
|
+
/**
|
|
347
|
+
* Method to stop the timer (if currently running) and prevent any memory
|
|
348
|
+
* leaks.
|
|
349
|
+
*
|
|
350
|
+
* @public
|
|
351
|
+
*/
|
|
352
|
+
shutdown(): void;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
export {
|
|
356
|
+
rateLimit as default,
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
export {};
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
// Generated by dts-bundle-generator v7.0.0
|
|
2
|
+
|
|
3
|
+
import { NextFunction, Request, RequestHandler, Response } from 'express';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Callback that fires when a client's hit counter is incremented.
|
|
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.
|
|
11
|
+
*/
|
|
12
|
+
export type IncrementCallback = (error: Error | undefined, totalHits: number, resetTime: Date | undefined) => void;
|
|
13
|
+
/**
|
|
14
|
+
* Method (in the form of middleware) to generate/retrieve a value based on the
|
|
15
|
+
* incoming request.
|
|
16
|
+
*
|
|
17
|
+
* @param request {Request} - The Express request object.
|
|
18
|
+
* @param response {Response} - The Express response object.
|
|
19
|
+
*
|
|
20
|
+
* @returns {T} - The value needed.
|
|
21
|
+
*/
|
|
22
|
+
export type ValueDeterminingMiddleware<T> = (request: Request, response: Response) => T | Promise<T>;
|
|
23
|
+
/**
|
|
24
|
+
* Express request handler that sends back a response when a client is
|
|
25
|
+
* rate-limited.
|
|
26
|
+
*
|
|
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
|
+
*/
|
|
32
|
+
export type RateLimitExceededEventHandler = (request: Request, response: Response, next: NextFunction, optionsUsed: Options) => void;
|
|
33
|
+
/**
|
|
34
|
+
* Event callback that is triggered on a client's first request that exceeds the limit
|
|
35
|
+
* but not for subsequent requests. May be used for logging, etc. Should *not*
|
|
36
|
+
* send a response.
|
|
37
|
+
*
|
|
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
|
+
*/
|
|
42
|
+
export type RateLimitReachedEventHandler = (request: Request, response: Response, optionsUsed: Options) => void;
|
|
43
|
+
/**
|
|
44
|
+
* Data returned from the `Store` when a client's hit counter is incremented.
|
|
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.
|
|
48
|
+
*/
|
|
49
|
+
export type IncrementResponse = {
|
|
50
|
+
totalHits: number;
|
|
51
|
+
resetTime: Date | undefined;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* A modified Express request handler with the rate limit functions.
|
|
55
|
+
*/
|
|
56
|
+
export type RateLimitRequestHandler = RequestHandler & {
|
|
57
|
+
/**
|
|
58
|
+
* Method to reset a client's hit counter.
|
|
59
|
+
*
|
|
60
|
+
* @param key {string} - The identifier for a client.
|
|
61
|
+
*/
|
|
62
|
+
resetKey: (key: string) => void;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* An interface that all hit counter stores must implement.
|
|
66
|
+
*
|
|
67
|
+
* @deprecated 6.x - Implement the `Store` interface instead.
|
|
68
|
+
*/
|
|
69
|
+
export type LegacyStore = {
|
|
70
|
+
/**
|
|
71
|
+
* Method to increment a client's hit counter.
|
|
72
|
+
*
|
|
73
|
+
* @param key {string} - The identifier for a client.
|
|
74
|
+
* @param callback {IncrementCallback} - The callback to call once the counter is incremented.
|
|
75
|
+
*/
|
|
76
|
+
incr: (key: string, callback: IncrementCallback) => void;
|
|
77
|
+
/**
|
|
78
|
+
* Method to decrement a client's hit counter.
|
|
79
|
+
*
|
|
80
|
+
* @param key {string} - The identifier for a client.
|
|
81
|
+
*/
|
|
82
|
+
decrement: (key: string) => void;
|
|
83
|
+
/**
|
|
84
|
+
* Method to reset a client's hit counter.
|
|
85
|
+
*
|
|
86
|
+
* @param key {string} - The identifier for a client.
|
|
87
|
+
*/
|
|
88
|
+
resetKey: (key: string) => void;
|
|
89
|
+
/**
|
|
90
|
+
* Method to reset everyone's hit counter.
|
|
91
|
+
*/
|
|
92
|
+
resetAll?: () => void;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* An interface that all hit counter stores must implement.
|
|
96
|
+
*/
|
|
97
|
+
export type Store = {
|
|
98
|
+
/**
|
|
99
|
+
* Method that initializes the store, and has access to the options passed to
|
|
100
|
+
* the middleware too.
|
|
101
|
+
*
|
|
102
|
+
* @param options {Options} - The options used to setup the middleware.
|
|
103
|
+
*/
|
|
104
|
+
init?: (options: Options) => void;
|
|
105
|
+
/**
|
|
106
|
+
* Method to increment a client's hit counter.
|
|
107
|
+
*
|
|
108
|
+
* @param key {string} - The identifier for a client.
|
|
109
|
+
*
|
|
110
|
+
* @returns {IncrementResponse} - The number of hits and reset time for that client.
|
|
111
|
+
*/
|
|
112
|
+
increment: (key: string) => Promise<IncrementResponse> | IncrementResponse;
|
|
113
|
+
/**
|
|
114
|
+
* Method to decrement a client's hit counter.
|
|
115
|
+
*
|
|
116
|
+
* @param key {string} - The identifier for a client.
|
|
117
|
+
*/
|
|
118
|
+
decrement: (key: string) => Promise<void> | void;
|
|
119
|
+
/**
|
|
120
|
+
* Method to reset a client's hit counter.
|
|
121
|
+
*
|
|
122
|
+
* @param key {string} - The identifier for a client.
|
|
123
|
+
*/
|
|
124
|
+
resetKey: (key: string) => Promise<void> | void;
|
|
125
|
+
/**
|
|
126
|
+
* Method to reset everyone's hit counter.
|
|
127
|
+
*/
|
|
128
|
+
resetAll?: () => Promise<void> | void;
|
|
129
|
+
/**
|
|
130
|
+
* Method to shutdown the store, stop timers, and release all resources.
|
|
131
|
+
*/
|
|
132
|
+
shutdown?: () => Promise<void> | void;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* The configuration options for the rate limiter.
|
|
136
|
+
*/
|
|
137
|
+
export type Options = {
|
|
138
|
+
/**
|
|
139
|
+
* How long we should remember the requests.
|
|
140
|
+
*
|
|
141
|
+
* Defaults to `60000` ms (= 1 minute).
|
|
142
|
+
*/
|
|
143
|
+
readonly windowMs: number;
|
|
144
|
+
/**
|
|
145
|
+
* The maximum number of connections to allow during the `window` before
|
|
146
|
+
* rate limiting the client.
|
|
147
|
+
*
|
|
148
|
+
* Can be the limit itself as a number or express middleware that parses
|
|
149
|
+
* the request and then figures out the limit.
|
|
150
|
+
*
|
|
151
|
+
* Defaults to `5`.
|
|
152
|
+
*/
|
|
153
|
+
readonly max: number | ValueDeterminingMiddleware<number>;
|
|
154
|
+
/**
|
|
155
|
+
* The response body to send back when a client is rate limited.
|
|
156
|
+
*
|
|
157
|
+
* Defaults to `'Too many requests, please try again later.'`
|
|
158
|
+
*/
|
|
159
|
+
readonly message: any | ValueDeterminingMiddleware<any>;
|
|
160
|
+
/**
|
|
161
|
+
* The HTTP status code to send back when a client is rate limited.
|
|
162
|
+
*
|
|
163
|
+
* Defaults to `HTTP 429 Too Many Requests` (RFC 6585).
|
|
164
|
+
*/
|
|
165
|
+
readonly statusCode: number;
|
|
166
|
+
/**
|
|
167
|
+
* Whether to send `X-RateLimit-*` headers with the rate limit and the number
|
|
168
|
+
* of requests.
|
|
169
|
+
*
|
|
170
|
+
* Defaults to `true` (for backward compatibility).
|
|
171
|
+
*/
|
|
172
|
+
readonly legacyHeaders: boolean;
|
|
173
|
+
/**
|
|
174
|
+
* Whether to enable support for the standardized rate limit headers (`RateLimit-*`).
|
|
175
|
+
*
|
|
176
|
+
* Defaults to `false` (for backward compatibility, but its use is recommended).
|
|
177
|
+
*/
|
|
178
|
+
readonly standardHeaders: boolean;
|
|
179
|
+
/**
|
|
180
|
+
* The name of the property on the request object to store the rate limit info.
|
|
181
|
+
*
|
|
182
|
+
* Defaults to `rateLimit`.
|
|
183
|
+
*/
|
|
184
|
+
readonly requestPropertyName: string;
|
|
185
|
+
/**
|
|
186
|
+
* If `true`, the library will (by default) skip all requests that have a 4XX
|
|
187
|
+
* or 5XX status.
|
|
188
|
+
*
|
|
189
|
+
* Defaults to `false`.
|
|
190
|
+
*/
|
|
191
|
+
readonly skipFailedRequests: boolean;
|
|
192
|
+
/**
|
|
193
|
+
* If `true`, the library will (by default) skip all requests that have a
|
|
194
|
+
* status code less than 400.
|
|
195
|
+
*
|
|
196
|
+
* Defaults to `false`.
|
|
197
|
+
*/
|
|
198
|
+
readonly skipSuccessfulRequests: boolean;
|
|
199
|
+
/**
|
|
200
|
+
* Method to generate custom identifiers for clients.
|
|
201
|
+
*
|
|
202
|
+
* By default, the client's IP address is used.
|
|
203
|
+
*/
|
|
204
|
+
readonly keyGenerator: ValueDeterminingMiddleware<string>;
|
|
205
|
+
/**
|
|
206
|
+
* Express request handler that sends back a response when a client is
|
|
207
|
+
* rate-limited.
|
|
208
|
+
*
|
|
209
|
+
* By default, sends back the `statusCode` and `message` set via the options.
|
|
210
|
+
*/
|
|
211
|
+
readonly handler: RateLimitExceededEventHandler;
|
|
212
|
+
/**
|
|
213
|
+
* Express request handler that sends back a response when a client has
|
|
214
|
+
* reached their rate limit, and will be rate limited on their next request.
|
|
215
|
+
*
|
|
216
|
+
* @deprecated 6.x - Please use a custom `handler` that checks the number of
|
|
217
|
+
* hits instead.
|
|
218
|
+
*/
|
|
219
|
+
readonly onLimitReached: RateLimitReachedEventHandler;
|
|
220
|
+
/**
|
|
221
|
+
* Method (in the form of middleware) to determine whether or not this request
|
|
222
|
+
* counts towards a client's quota.
|
|
223
|
+
*
|
|
224
|
+
* By default, skips no requests.
|
|
225
|
+
*/
|
|
226
|
+
readonly skip: ValueDeterminingMiddleware<boolean>;
|
|
227
|
+
/**
|
|
228
|
+
* Method to determine whether or not the request counts as 'succesful'. Used
|
|
229
|
+
* when either `skipSuccessfulRequests` or `skipFailedRequests` is set to true.
|
|
230
|
+
*
|
|
231
|
+
* By default, requests with a response status code less than 400 are considered
|
|
232
|
+
* successful.
|
|
233
|
+
*/
|
|
234
|
+
readonly requestWasSuccessful: ValueDeterminingMiddleware<boolean>;
|
|
235
|
+
/**
|
|
236
|
+
* The `Store` to use to store the hit count for each client.
|
|
237
|
+
*
|
|
238
|
+
* By default, the built-in `MemoryStore` will be used.
|
|
239
|
+
*/
|
|
240
|
+
store: Store | LegacyStore;
|
|
241
|
+
/**
|
|
242
|
+
* Whether to send `X-RateLimit-*` headers with the rate limit and the number
|
|
243
|
+
* of requests.
|
|
244
|
+
*
|
|
245
|
+
* @deprecated 6.x - This option was renamed to `legacyHeaders`.
|
|
246
|
+
*/
|
|
247
|
+
headers?: boolean;
|
|
248
|
+
/**
|
|
249
|
+
* Whether to send `RateLimit-*` headers with the rate limit and the number
|
|
250
|
+
* of requests.
|
|
251
|
+
*
|
|
252
|
+
* @deprecated 6.x - This option was renamed to `standardHeaders`.
|
|
253
|
+
*/
|
|
254
|
+
draft_polli_ratelimit_headers?: boolean;
|
|
255
|
+
};
|
|
256
|
+
/**
|
|
257
|
+
* The extended request object that includes information about the client's
|
|
258
|
+
* rate limit.
|
|
259
|
+
*/
|
|
260
|
+
export type AugmentedRequest = Request & {
|
|
261
|
+
[key: string]: RateLimitInfo;
|
|
262
|
+
};
|
|
263
|
+
/**
|
|
264
|
+
* The rate limit related information for each client included in the
|
|
265
|
+
* Express request object.
|
|
266
|
+
*/
|
|
267
|
+
export type RateLimitInfo = {
|
|
268
|
+
readonly limit: number;
|
|
269
|
+
readonly current: number;
|
|
270
|
+
readonly remaining: number;
|
|
271
|
+
readonly resetTime: Date | undefined;
|
|
272
|
+
};
|
|
273
|
+
/**
|
|
274
|
+
*
|
|
275
|
+
* Create an instance of IP rate-limiting middleware for Express.
|
|
276
|
+
*
|
|
277
|
+
* @param passedOptions {Options} - Options to configure the rate limiter.
|
|
278
|
+
*
|
|
279
|
+
* @returns {RateLimitRequestHandler} - The middleware that rate-limits clients based on your configuration.
|
|
280
|
+
*
|
|
281
|
+
* @public
|
|
282
|
+
*/
|
|
283
|
+
export declare const rateLimit: (passedOptions?: Partial<Options>) => RateLimitRequestHandler;
|
|
284
|
+
/**
|
|
285
|
+
* A `Store` that stores the hit count for each client in memory.
|
|
286
|
+
*
|
|
287
|
+
* @public
|
|
288
|
+
*/
|
|
289
|
+
export declare class MemoryStore implements Store {
|
|
290
|
+
/**
|
|
291
|
+
* The duration of time before which all hit counts are reset (in milliseconds).
|
|
292
|
+
*/
|
|
293
|
+
windowMs: number;
|
|
294
|
+
/**
|
|
295
|
+
* The map that stores the number of hits for each client in memory.
|
|
296
|
+
*/
|
|
297
|
+
hits: {
|
|
298
|
+
[key: string]: number | undefined;
|
|
299
|
+
};
|
|
300
|
+
/**
|
|
301
|
+
* The time at which all hit counts will be reset.
|
|
302
|
+
*/
|
|
303
|
+
resetTime: Date;
|
|
304
|
+
/**
|
|
305
|
+
* Reference to the active timer.
|
|
306
|
+
*/
|
|
307
|
+
interval?: NodeJS.Timer;
|
|
308
|
+
/**
|
|
309
|
+
* Method that initializes the store.
|
|
310
|
+
*
|
|
311
|
+
* @param options {Options} - The options used to setup the middleware.
|
|
312
|
+
*/
|
|
313
|
+
init(options: Options): void;
|
|
314
|
+
/**
|
|
315
|
+
* Method to increment a client's hit counter.
|
|
316
|
+
*
|
|
317
|
+
* @param key {string} - The identifier for a client.
|
|
318
|
+
*
|
|
319
|
+
* @returns {IncrementResponse} - The number of hits and reset time for that client.
|
|
320
|
+
*
|
|
321
|
+
* @public
|
|
322
|
+
*/
|
|
323
|
+
increment(key: string): Promise<IncrementResponse>;
|
|
324
|
+
/**
|
|
325
|
+
* Method to decrement a client's hit counter.
|
|
326
|
+
*
|
|
327
|
+
* @param key {string} - The identifier for a client.
|
|
328
|
+
*
|
|
329
|
+
* @public
|
|
330
|
+
*/
|
|
331
|
+
decrement(key: string): Promise<void>;
|
|
332
|
+
/**
|
|
333
|
+
* Method to reset a client's hit counter.
|
|
334
|
+
*
|
|
335
|
+
* @param key {string} - The identifier for a client.
|
|
336
|
+
*
|
|
337
|
+
* @public
|
|
338
|
+
*/
|
|
339
|
+
resetKey(key: string): Promise<void>;
|
|
340
|
+
/**
|
|
341
|
+
* Method to reset everyone's hit counter.
|
|
342
|
+
*
|
|
343
|
+
* @public
|
|
344
|
+
*/
|
|
345
|
+
resetAll(): Promise<void>;
|
|
346
|
+
/**
|
|
347
|
+
* Method to stop the timer (if currently running) and prevent any memory
|
|
348
|
+
* leaks.
|
|
349
|
+
*
|
|
350
|
+
* @public
|
|
351
|
+
*/
|
|
352
|
+
shutdown(): void;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
export {
|
|
356
|
+
rateLimit as default,
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { NextFunction, Request, RequestHandler, Response } from 'express';
|
|
|
9
9
|
* @param totalHits {number} - The number of hits for that client so far.
|
|
10
10
|
* @param resetTime {Date | undefined} - The time when the counter resets.
|
|
11
11
|
*/
|
|
12
|
-
export
|
|
12
|
+
export 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
15
|
* incoming request.
|
|
@@ -19,7 +19,7 @@ export declare type IncrementCallback = (error: Error | undefined, totalHits: nu
|
|
|
19
19
|
*
|
|
20
20
|
* @returns {T} - The value needed.
|
|
21
21
|
*/
|
|
22
|
-
export
|
|
22
|
+
export 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.
|
|
@@ -29,7 +29,7 @@ export declare type ValueDeterminingMiddleware<T> = (request: Request, response:
|
|
|
29
29
|
* @param next {NextFunction} - The Express `next` function, can be called to skip responding.
|
|
30
30
|
* @param optionsUsed {Options} - The options used to set up the middleware.
|
|
31
31
|
*/
|
|
32
|
-
export
|
|
32
|
+
export 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*
|
|
@@ -39,21 +39,21 @@ export declare type RateLimitExceededEventHandler = (request: Request, response:
|
|
|
39
39
|
* @param response {Response} - The Express response object.
|
|
40
40
|
* @param optionsUsed {Options} - The options used to set up the middleware.
|
|
41
41
|
*/
|
|
42
|
-
export
|
|
42
|
+
export 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
46
|
* @property totalHits {number} - The number of hits for that client so far.
|
|
47
47
|
* @property resetTime {Date | undefined} - The time when the counter resets.
|
|
48
48
|
*/
|
|
49
|
-
export
|
|
49
|
+
export type IncrementResponse = {
|
|
50
50
|
totalHits: number;
|
|
51
51
|
resetTime: Date | undefined;
|
|
52
52
|
};
|
|
53
53
|
/**
|
|
54
54
|
* A modified Express request handler with the rate limit functions.
|
|
55
55
|
*/
|
|
56
|
-
export
|
|
56
|
+
export type RateLimitRequestHandler = RequestHandler & {
|
|
57
57
|
/**
|
|
58
58
|
* Method to reset a client's hit counter.
|
|
59
59
|
*
|
|
@@ -66,7 +66,7 @@ export declare type RateLimitRequestHandler = RequestHandler & {
|
|
|
66
66
|
*
|
|
67
67
|
* @deprecated 6.x - Implement the `Store` interface instead.
|
|
68
68
|
*/
|
|
69
|
-
export
|
|
69
|
+
export type LegacyStore = {
|
|
70
70
|
/**
|
|
71
71
|
* Method to increment a client's hit counter.
|
|
72
72
|
*
|
|
@@ -94,7 +94,7 @@ export declare type LegacyStore = {
|
|
|
94
94
|
/**
|
|
95
95
|
* An interface that all hit counter stores must implement.
|
|
96
96
|
*/
|
|
97
|
-
export
|
|
97
|
+
export type Store = {
|
|
98
98
|
/**
|
|
99
99
|
* Method that initializes the store, and has access to the options passed to
|
|
100
100
|
* the middleware too.
|
|
@@ -134,7 +134,7 @@ export declare type Store = {
|
|
|
134
134
|
/**
|
|
135
135
|
* The configuration options for the rate limiter.
|
|
136
136
|
*/
|
|
137
|
-
export
|
|
137
|
+
export type Options = {
|
|
138
138
|
/**
|
|
139
139
|
* How long we should remember the requests.
|
|
140
140
|
*
|
|
@@ -257,14 +257,14 @@ export declare type Options = {
|
|
|
257
257
|
* The extended request object that includes information about the client's
|
|
258
258
|
* rate limit.
|
|
259
259
|
*/
|
|
260
|
-
export
|
|
260
|
+
export type AugmentedRequest = Request & {
|
|
261
261
|
[key: string]: RateLimitInfo;
|
|
262
262
|
};
|
|
263
263
|
/**
|
|
264
264
|
* The rate limit related information for each client included in the
|
|
265
265
|
* Express request object.
|
|
266
266
|
*/
|
|
267
|
-
export
|
|
267
|
+
export type RateLimitInfo = {
|
|
268
268
|
readonly limit: number;
|
|
269
269
|
readonly current: number;
|
|
270
270
|
readonly remaining: number;
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,40 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => {
|
|
4
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
|
+
return value;
|
|
6
|
+
};
|
|
7
|
+
|
|
1
8
|
// source/memory-store.ts
|
|
2
9
|
var calculateNextResetTime = (windowMs) => {
|
|
3
|
-
const resetTime = new Date();
|
|
10
|
+
const resetTime = /* @__PURE__ */ new Date();
|
|
4
11
|
resetTime.setMilliseconds(resetTime.getMilliseconds() + windowMs);
|
|
5
12
|
return resetTime;
|
|
6
13
|
};
|
|
7
14
|
var MemoryStore = class {
|
|
15
|
+
constructor() {
|
|
16
|
+
/**
|
|
17
|
+
* The duration of time before which all hit counts are reset (in milliseconds).
|
|
18
|
+
*/
|
|
19
|
+
__publicField(this, "windowMs");
|
|
20
|
+
/**
|
|
21
|
+
* The map that stores the number of hits for each client in memory.
|
|
22
|
+
*/
|
|
23
|
+
__publicField(this, "hits");
|
|
24
|
+
/**
|
|
25
|
+
* The time at which all hit counts will be reset.
|
|
26
|
+
*/
|
|
27
|
+
__publicField(this, "resetTime");
|
|
28
|
+
/**
|
|
29
|
+
* Reference to the active timer.
|
|
30
|
+
*/
|
|
31
|
+
__publicField(this, "interval");
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Method that initializes the store.
|
|
35
|
+
*
|
|
36
|
+
* @param options {Options} - The options used to setup the middleware.
|
|
37
|
+
*/
|
|
8
38
|
init(options) {
|
|
9
39
|
this.windowMs = options.windowMs;
|
|
10
40
|
this.resetTime = calculateNextResetTime(this.windowMs);
|
|
@@ -15,6 +45,15 @@ var MemoryStore = class {
|
|
|
15
45
|
if (this.interval.unref)
|
|
16
46
|
this.interval.unref();
|
|
17
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Method to increment a client's hit counter.
|
|
50
|
+
*
|
|
51
|
+
* @param key {string} - The identifier for a client.
|
|
52
|
+
*
|
|
53
|
+
* @returns {IncrementResponse} - The number of hits and reset time for that client.
|
|
54
|
+
*
|
|
55
|
+
* @public
|
|
56
|
+
*/
|
|
18
57
|
async increment(key) {
|
|
19
58
|
var _a;
|
|
20
59
|
const totalHits = ((_a = this.hits[key]) != null ? _a : 0) + 1;
|
|
@@ -24,25 +63,54 @@ var MemoryStore = class {
|
|
|
24
63
|
resetTime: this.resetTime
|
|
25
64
|
};
|
|
26
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Method to decrement a client's hit counter.
|
|
68
|
+
*
|
|
69
|
+
* @param key {string} - The identifier for a client.
|
|
70
|
+
*
|
|
71
|
+
* @public
|
|
72
|
+
*/
|
|
27
73
|
async decrement(key) {
|
|
28
74
|
const current = this.hits[key];
|
|
29
75
|
if (current)
|
|
30
76
|
this.hits[key] = current - 1;
|
|
31
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Method to reset a client's hit counter.
|
|
80
|
+
*
|
|
81
|
+
* @param key {string} - The identifier for a client.
|
|
82
|
+
*
|
|
83
|
+
* @public
|
|
84
|
+
*/
|
|
32
85
|
async resetKey(key) {
|
|
33
86
|
delete this.hits[key];
|
|
34
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Method to reset everyone's hit counter.
|
|
90
|
+
*
|
|
91
|
+
* @public
|
|
92
|
+
*/
|
|
35
93
|
async resetAll() {
|
|
36
94
|
this.hits = {};
|
|
37
95
|
this.resetTime = calculateNextResetTime(this.windowMs);
|
|
38
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Method to stop the timer (if currently running) and prevent any memory
|
|
99
|
+
* leaks.
|
|
100
|
+
*
|
|
101
|
+
* @public
|
|
102
|
+
*/
|
|
39
103
|
shutdown() {
|
|
40
104
|
clearInterval(this.interval);
|
|
41
105
|
}
|
|
42
106
|
};
|
|
43
107
|
|
|
44
108
|
// source/lib.ts
|
|
45
|
-
var isLegacyStore = (store) =>
|
|
109
|
+
var isLegacyStore = (store) => (
|
|
110
|
+
// Check that `incr` exists but `increment` does not - store authors might want
|
|
111
|
+
// to keep both around for backwards compatibility.
|
|
112
|
+
typeof store.incr === "function" && typeof store.increment !== "function"
|
|
113
|
+
);
|
|
46
114
|
var promisifyStore = (passedStore) => {
|
|
47
115
|
if (!isLegacyStore(passedStore)) {
|
|
48
116
|
return passedStore;
|
|
@@ -109,10 +177,13 @@ var parseOptions = (passedOptions) => {
|
|
|
109
177
|
},
|
|
110
178
|
onLimitReached(_request, _response, _optionsUsed) {
|
|
111
179
|
},
|
|
180
|
+
// Allow the options object to be overriden by the options passed to the middleware.
|
|
112
181
|
...notUndefinedOptions,
|
|
182
|
+
// Note that this field is declared after the user's options are spread in,
|
|
183
|
+
// so that this field doesn't get overriden with an un-promisified store!
|
|
113
184
|
store: promisifyStore((_c = notUndefinedOptions.store) != null ? _c : new MemoryStore())
|
|
114
185
|
};
|
|
115
|
-
if (typeof config.store.increment !== "function" || typeof config.store.decrement !== "function" || typeof config.store.resetKey !== "function" ||
|
|
186
|
+
if (typeof config.store.increment !== "function" || typeof config.store.decrement !== "function" || typeof config.store.resetKey !== "function" || config.store.resetAll !== void 0 && typeof config.store.resetAll !== "function" || config.store.init !== void 0 && typeof config.store.init !== "function") {
|
|
116
187
|
throw new TypeError(
|
|
117
188
|
"An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface."
|
|
118
189
|
);
|
|
@@ -155,7 +226,7 @@ var rateLimit = (passedOptions) => {
|
|
|
155
226
|
augmentedRequest[options.requestPropertyName].remaining
|
|
156
227
|
);
|
|
157
228
|
if (resetTime instanceof Date) {
|
|
158
|
-
response.setHeader("Date", new Date().toUTCString());
|
|
229
|
+
response.setHeader("Date", (/* @__PURE__ */ new Date()).toUTCString());
|
|
159
230
|
response.setHeader(
|
|
160
231
|
"X-RateLimit-Reset",
|
|
161
232
|
Math.ceil(resetTime.getTime() / 1e3)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "express-rate-limit",
|
|
3
|
-
"version": "6.7.
|
|
3
|
+
"version": "6.7.2",
|
|
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",
|
|
@@ -30,9 +30,14 @@
|
|
|
30
30
|
"type": "module",
|
|
31
31
|
"exports": {
|
|
32
32
|
".": {
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
"import": {
|
|
34
|
+
"types": "./dist/index.d.mts",
|
|
35
|
+
"default": "./dist/index.mjs"
|
|
36
|
+
},
|
|
37
|
+
"require": {
|
|
38
|
+
"types": "./dist/index.d.cts",
|
|
39
|
+
"default": "./dist/index.cjs"
|
|
40
|
+
}
|
|
36
41
|
}
|
|
37
42
|
},
|
|
38
43
|
"main": "./dist/index.cjs",
|
|
@@ -47,19 +52,19 @@
|
|
|
47
52
|
"changelog.md"
|
|
48
53
|
],
|
|
49
54
|
"engines": {
|
|
50
|
-
"node": ">=
|
|
55
|
+
"node": ">= 14.0.0"
|
|
51
56
|
},
|
|
52
57
|
"scripts": {
|
|
53
58
|
"clean": "del-cli dist/ coverage/ *.log *.tmp *.bak *.tgz",
|
|
54
59
|
"build:cjs": "esbuild --bundle --target=es2019 --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",
|
|
55
60
|
"build:esm": "esbuild --bundle --target=es2019 --format=esm --outfile=dist/index.mjs source/index.ts",
|
|
56
|
-
"build:types": "dts-bundle-generator --out-file=dist/index.d.ts source/index.ts",
|
|
61
|
+
"build:types": "dts-bundle-generator --out-file=dist/index.d.ts source/index.ts && cp dist/index.d.ts dist/index.d.cts && cp dist/index.d.ts dist/index.d.mts",
|
|
57
62
|
"compile": "run-s clean build:*",
|
|
58
63
|
"lint:code": "xo --ignore test/external/",
|
|
59
64
|
"lint:rest": "prettier --ignore-path .gitignore --ignore-unknown --check .",
|
|
60
65
|
"lint": "run-s lint:*",
|
|
61
|
-
"autofix:code": "
|
|
62
|
-
"autofix:rest": "
|
|
66
|
+
"autofix:code": "run-s lint:code --fix",
|
|
67
|
+
"autofix:rest": "run-s lint:rest --write .",
|
|
63
68
|
"autofix": "run-s autofix:*",
|
|
64
69
|
"test:lib": "cross-env NODE_OPTIONS=--experimental-vm-modules jest",
|
|
65
70
|
"test:ext": "cd test/external/ && bash run-all-tests",
|
|
@@ -71,25 +76,25 @@
|
|
|
71
76
|
"express": "^4 || ^5"
|
|
72
77
|
},
|
|
73
78
|
"devDependencies": {
|
|
74
|
-
"@jest/globals": "29.
|
|
75
|
-
"@types/express": "4.17.
|
|
76
|
-
"@types/jest": "29.2
|
|
77
|
-
"@types/node": "
|
|
79
|
+
"@jest/globals": "29.6.1",
|
|
80
|
+
"@types/express": "4.17.17",
|
|
81
|
+
"@types/jest": "29.5.2",
|
|
82
|
+
"@types/node": "20.4.0",
|
|
78
83
|
"@types/supertest": "2.0.12",
|
|
79
84
|
"cross-env": "7.0.3",
|
|
80
85
|
"del-cli": "5.0.0",
|
|
81
86
|
"dts-bundle-generator": "7.0.0",
|
|
82
|
-
"esbuild": "0.
|
|
87
|
+
"esbuild": "0.18.11",
|
|
83
88
|
"express": "4.18.2",
|
|
84
|
-
"husky": "8.0.
|
|
85
|
-
"jest": "29.
|
|
86
|
-
"lint-staged": "13.
|
|
89
|
+
"husky": "8.0.3",
|
|
90
|
+
"jest": "29.6.1",
|
|
91
|
+
"lint-staged": "13.2.3",
|
|
87
92
|
"npm-run-all": "4.1.5",
|
|
88
|
-
"supertest": "6.3.
|
|
89
|
-
"ts-jest": "29.
|
|
93
|
+
"supertest": "6.3.3",
|
|
94
|
+
"ts-jest": "29.1.1",
|
|
90
95
|
"ts-node": "10.9.1",
|
|
91
|
-
"typescript": "4.
|
|
92
|
-
"xo": "0.
|
|
96
|
+
"typescript": "4.9.5",
|
|
97
|
+
"xo": "0.54.2"
|
|
93
98
|
},
|
|
94
99
|
"xo": {
|
|
95
100
|
"prettier": true,
|
package/readme.md
CHANGED
|
@@ -355,7 +355,8 @@ Defaults to `false`.
|
|
|
355
355
|
|
|
356
356
|
> `function`
|
|
357
357
|
|
|
358
|
-
Method to
|
|
358
|
+
Method to retrieve custom identifiers for clients, such as their IP address,
|
|
359
|
+
username, or API Key.
|
|
359
360
|
|
|
360
361
|
Should be a (sync/async) function that accepts the Express `request` and
|
|
361
362
|
`response` objects and then returns a string.
|
|
@@ -369,6 +370,10 @@ const limiter = rateLimit({
|
|
|
369
370
|
})
|
|
370
371
|
```
|
|
371
372
|
|
|
373
|
+
> **Note** If a `keyGenerator` returns the same value for every user, it becomes
|
|
374
|
+
> a global rate limiter. This could be combined with a second instance of
|
|
375
|
+
> `express-rate-limit` to have both global and per-user limits.
|
|
376
|
+
|
|
372
377
|
### `handler`
|
|
373
378
|
|
|
374
379
|
> `function`
|