express-rate-limit 6.7.0 → 6.8.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 +27 -4
- package/dist/index.cjs +240 -46
- package/dist/index.d.cts +363 -0
- package/dist/index.d.mts +363 -0
- package/dist/index.d.ts +34 -30
- package/dist/index.mjs +237 -46
- package/package.json +38 -31
- package/readme.md +21 -1
package/changelog.md
CHANGED
|
@@ -6,15 +6,38 @@ 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.8.0](https://github.com/express-rate-limit/express-rate-limit/releases/tag/v6.8.0)
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Added a set of validation checks to execute on the first request. (See
|
|
14
|
+
[#358](https://github.com/express-rate-limit/express-rate-limit/issues/358))
|
|
15
|
+
|
|
16
|
+
## [6.7.1](https://github.com/express-rate-limit/express-rate-limit/releases/tag/v6.7.1)
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- Fixed compatibility with TypeScript's TypeScript new `node16` module
|
|
21
|
+
resolution strategy (See
|
|
22
|
+
[#355](https://github.com/express-rate-limit/express-rate-limit/issues/355))
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Bumped development dependencies.
|
|
27
|
+
- Added `node` 20 to list of versions the CI jobs run on.
|
|
28
|
+
|
|
29
|
+
No functional changes.
|
|
30
|
+
|
|
9
31
|
## [6.7.0](https://github.com/express-rate-limit/express-rate-limit/releases/tag/v6.7.0)
|
|
10
32
|
|
|
11
33
|
### Changed
|
|
12
34
|
|
|
13
|
-
- Updated links to point to new express-rate-limit organization on GitHub.
|
|
14
|
-
- Added advertisement to
|
|
35
|
+
- Updated links to point to the new `express-rate-limit` organization on GitHub.
|
|
36
|
+
- Added advertisement to `readme.md` for project sponsor
|
|
15
37
|
[Zuplo](https://zuplo.link/express-rate-limit).
|
|
16
|
-
- Updated
|
|
17
|
-
-
|
|
38
|
+
- Updated to `typescript` version 5 and bumped other dependencies.
|
|
39
|
+
- Dropped `node` 12, and added `node` 19 to the list of versions the CI jobs run
|
|
40
|
+
on.
|
|
18
41
|
|
|
19
42
|
No functional changes.
|
|
20
43
|
|
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 = {};
|
|
@@ -26,13 +31,146 @@ __export(source_exports, {
|
|
|
26
31
|
});
|
|
27
32
|
module.exports = __toCommonJS(source_exports);
|
|
28
33
|
|
|
34
|
+
// source/validations.ts
|
|
35
|
+
var import_node_net = require("net");
|
|
36
|
+
var ValidationError = class extends Error {
|
|
37
|
+
/**
|
|
38
|
+
* The code must be a string, in snake case and all capital, that starts with
|
|
39
|
+
* the substring `ERR_ERL_`.
|
|
40
|
+
*
|
|
41
|
+
* The message must be a string, starting with a lowercase character,
|
|
42
|
+
* describing the issue in detail.
|
|
43
|
+
*/
|
|
44
|
+
constructor(code, message) {
|
|
45
|
+
super(
|
|
46
|
+
`express-rate-limit: ${code} - ${message} See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#${code.toLowerCase()} for more information on this error.`
|
|
47
|
+
);
|
|
48
|
+
__publicField(this, "name");
|
|
49
|
+
__publicField(this, "code");
|
|
50
|
+
this.name = this.constructor.name;
|
|
51
|
+
this.code = code;
|
|
52
|
+
this.message = message;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var Validations = class {
|
|
56
|
+
constructor(enabled) {
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/parameter-properties
|
|
58
|
+
__publicField(this, "enabled");
|
|
59
|
+
this.enabled = enabled;
|
|
60
|
+
}
|
|
61
|
+
enable() {
|
|
62
|
+
this.enabled = true;
|
|
63
|
+
}
|
|
64
|
+
disable() {
|
|
65
|
+
this.enabled = false;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Checks whether the IP address is valid, and that it does not have a port
|
|
69
|
+
* number in it.
|
|
70
|
+
*
|
|
71
|
+
* See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_invalid_ip_address.
|
|
72
|
+
*
|
|
73
|
+
* @param ip {string | undefined} - The IP address provided by Express as request.ip.
|
|
74
|
+
*
|
|
75
|
+
* @returns {void}
|
|
76
|
+
*/
|
|
77
|
+
ip(ip) {
|
|
78
|
+
this.wrap(() => {
|
|
79
|
+
if (ip === void 0) {
|
|
80
|
+
throw new ValidationError(
|
|
81
|
+
"ERR_ERL_UNDEFINED_IP_ADDRESS",
|
|
82
|
+
`An undefined 'request.ip' was detected. This might indicate a misconfiguration or the connection being destroyed prematurely.`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
if (!(0, import_node_net.isIP)(ip)) {
|
|
86
|
+
throw new ValidationError(
|
|
87
|
+
"ERR_ERL_INVALID_IP_ADDRESS",
|
|
88
|
+
`An invalid 'request.ip' (${ip}) was detected. Consider passing a custom 'keyGenerator' function to the rate limiter.`
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Makes sure the trust proxy setting is not set to `true`.
|
|
95
|
+
*
|
|
96
|
+
* See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_permissive_trust_proxy.
|
|
97
|
+
*
|
|
98
|
+
* @param request {Request} - The Express request object.
|
|
99
|
+
*
|
|
100
|
+
* @returns {void}
|
|
101
|
+
*/
|
|
102
|
+
trustProxy(request) {
|
|
103
|
+
this.wrap(() => {
|
|
104
|
+
if (request.app.get("trust proxy") === true) {
|
|
105
|
+
throw new ValidationError(
|
|
106
|
+
"ERR_ERL_PERMISSIVE_TRUST_PROXY",
|
|
107
|
+
`The Express 'trust proxy' setting is true, which allows anyone to trivially bypass IP-based rate limiting.`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Makes sure the trust proxy setting is set in case the `X-Forwarded-For`
|
|
114
|
+
* header is present.
|
|
115
|
+
*
|
|
116
|
+
* See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_unset_trust_proxy.
|
|
117
|
+
*
|
|
118
|
+
* @param request {Request} - The Express request object.
|
|
119
|
+
*
|
|
120
|
+
* @returns {void}
|
|
121
|
+
*/
|
|
122
|
+
xForwardedForHeader(request) {
|
|
123
|
+
this.wrap(() => {
|
|
124
|
+
if (request.headers["x-forwarded-for"] && request.app.get("trust proxy") === false) {
|
|
125
|
+
throw new ValidationError(
|
|
126
|
+
"ERR_ERL_UNEXPECTED_X_FORWARDED_FOR",
|
|
127
|
+
`The 'X-Forwarded-For' header is set but the Express 'trust proxy' setting is false (default). This could indicate a misconfiguration which would prevent express-rate-limit from accurately identifying users.`
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
wrap(validation) {
|
|
133
|
+
if (!this.enabled) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
validation.call(this);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.error(error);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
29
144
|
// source/memory-store.ts
|
|
30
145
|
var calculateNextResetTime = (windowMs) => {
|
|
31
|
-
const resetTime = new Date();
|
|
146
|
+
const resetTime = /* @__PURE__ */ new Date();
|
|
32
147
|
resetTime.setMilliseconds(resetTime.getMilliseconds() + windowMs);
|
|
33
148
|
return resetTime;
|
|
34
149
|
};
|
|
35
150
|
var MemoryStore = class {
|
|
151
|
+
constructor() {
|
|
152
|
+
/**
|
|
153
|
+
* The duration of time before which all hit counts are reset (in milliseconds).
|
|
154
|
+
*/
|
|
155
|
+
__publicField(this, "windowMs");
|
|
156
|
+
/**
|
|
157
|
+
* The map that stores the number of hits for each client in memory.
|
|
158
|
+
*/
|
|
159
|
+
__publicField(this, "hits");
|
|
160
|
+
/**
|
|
161
|
+
* The time at which all hit counts will be reset.
|
|
162
|
+
*/
|
|
163
|
+
__publicField(this, "resetTime");
|
|
164
|
+
/**
|
|
165
|
+
* Reference to the active timer.
|
|
166
|
+
*/
|
|
167
|
+
__publicField(this, "interval");
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Method that initializes the store.
|
|
171
|
+
*
|
|
172
|
+
* @param options {Options} - The options used to setup the middleware.
|
|
173
|
+
*/
|
|
36
174
|
init(options) {
|
|
37
175
|
this.windowMs = options.windowMs;
|
|
38
176
|
this.resetTime = calculateNextResetTime(this.windowMs);
|
|
@@ -43,6 +181,15 @@ var MemoryStore = class {
|
|
|
43
181
|
if (this.interval.unref)
|
|
44
182
|
this.interval.unref();
|
|
45
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Method to increment a client's hit counter.
|
|
186
|
+
*
|
|
187
|
+
* @param key {string} - The identifier for a client.
|
|
188
|
+
*
|
|
189
|
+
* @returns {IncrementResponse} - The number of hits and reset time for that client.
|
|
190
|
+
*
|
|
191
|
+
* @public
|
|
192
|
+
*/
|
|
46
193
|
async increment(key) {
|
|
47
194
|
var _a;
|
|
48
195
|
const totalHits = ((_a = this.hits[key]) != null ? _a : 0) + 1;
|
|
@@ -52,25 +199,54 @@ var MemoryStore = class {
|
|
|
52
199
|
resetTime: this.resetTime
|
|
53
200
|
};
|
|
54
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* Method to decrement a client's hit counter.
|
|
204
|
+
*
|
|
205
|
+
* @param key {string} - The identifier for a client.
|
|
206
|
+
*
|
|
207
|
+
* @public
|
|
208
|
+
*/
|
|
55
209
|
async decrement(key) {
|
|
56
210
|
const current = this.hits[key];
|
|
57
211
|
if (current)
|
|
58
212
|
this.hits[key] = current - 1;
|
|
59
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Method to reset a client's hit counter.
|
|
216
|
+
*
|
|
217
|
+
* @param key {string} - The identifier for a client.
|
|
218
|
+
*
|
|
219
|
+
* @public
|
|
220
|
+
*/
|
|
60
221
|
async resetKey(key) {
|
|
61
222
|
delete this.hits[key];
|
|
62
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Method to reset everyone's hit counter.
|
|
226
|
+
*
|
|
227
|
+
* @public
|
|
228
|
+
*/
|
|
63
229
|
async resetAll() {
|
|
64
230
|
this.hits = {};
|
|
65
231
|
this.resetTime = calculateNextResetTime(this.windowMs);
|
|
66
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* Method to stop the timer (if currently running) and prevent any memory
|
|
235
|
+
* leaks.
|
|
236
|
+
*
|
|
237
|
+
* @public
|
|
238
|
+
*/
|
|
67
239
|
shutdown() {
|
|
68
240
|
clearInterval(this.interval);
|
|
69
241
|
}
|
|
70
242
|
};
|
|
71
243
|
|
|
72
244
|
// source/lib.ts
|
|
73
|
-
var isLegacyStore = (store) =>
|
|
245
|
+
var isLegacyStore = (store) => (
|
|
246
|
+
// Check that `incr` exists but `increment` does not - store authors might want
|
|
247
|
+
// to keep both around for backwards compatibility.
|
|
248
|
+
typeof store.incr === "function" && typeof store.increment !== "function"
|
|
249
|
+
);
|
|
74
250
|
var promisifyStore = (passedStore) => {
|
|
75
251
|
if (!isLegacyStore(passedStore)) {
|
|
76
252
|
return passedStore;
|
|
@@ -102,27 +278,43 @@ var promisifyStore = (passedStore) => {
|
|
|
102
278
|
}
|
|
103
279
|
return new PromisifiedStore();
|
|
104
280
|
};
|
|
281
|
+
var getOptionsFromConfig = (config) => {
|
|
282
|
+
const { validations, ...directlyPassableEntries } = config;
|
|
283
|
+
return {
|
|
284
|
+
...directlyPassableEntries,
|
|
285
|
+
validate: validations.enabled
|
|
286
|
+
};
|
|
287
|
+
};
|
|
288
|
+
var omitUndefinedOptions = (passedOptions) => {
|
|
289
|
+
const omittedOptions = {};
|
|
290
|
+
for (const k of Object.keys(passedOptions)) {
|
|
291
|
+
const key = k;
|
|
292
|
+
if (passedOptions[key] !== void 0) {
|
|
293
|
+
omittedOptions[key] = passedOptions[key];
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return omittedOptions;
|
|
297
|
+
};
|
|
105
298
|
var parseOptions = (passedOptions) => {
|
|
106
|
-
var _a, _b, _c;
|
|
299
|
+
var _a, _b, _c, _d;
|
|
107
300
|
const notUndefinedOptions = omitUndefinedOptions(passedOptions);
|
|
301
|
+
const validations = new Validations((_a = notUndefinedOptions == null ? void 0 : notUndefinedOptions.validate) != null ? _a : true);
|
|
108
302
|
const config = {
|
|
109
303
|
windowMs: 60 * 1e3,
|
|
110
304
|
max: 5,
|
|
111
305
|
message: "Too many requests, please try again later.",
|
|
112
306
|
statusCode: 429,
|
|
113
|
-
legacyHeaders: (
|
|
114
|
-
standardHeaders: (
|
|
307
|
+
legacyHeaders: (_b = passedOptions.headers) != null ? _b : true,
|
|
308
|
+
standardHeaders: (_c = passedOptions.draft_polli_ratelimit_headers) != null ? _c : false,
|
|
115
309
|
requestPropertyName: "rateLimit",
|
|
116
310
|
skipFailedRequests: false,
|
|
117
311
|
skipSuccessfulRequests: false,
|
|
118
312
|
requestWasSuccessful: (_request, response) => response.statusCode < 400,
|
|
119
313
|
skip: (_request, _response) => false,
|
|
120
314
|
keyGenerator(request, _response) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
);
|
|
125
|
-
}
|
|
315
|
+
validations.ip(request.ip);
|
|
316
|
+
validations.trustProxy(request);
|
|
317
|
+
validations.xForwardedForHeader(request);
|
|
126
318
|
return request.ip;
|
|
127
319
|
},
|
|
128
320
|
async handler(request, response, _next, _optionsUsed) {
|
|
@@ -137,10 +329,15 @@ var parseOptions = (passedOptions) => {
|
|
|
137
329
|
},
|
|
138
330
|
onLimitReached(_request, _response, _optionsUsed) {
|
|
139
331
|
},
|
|
332
|
+
// Allow the options object to be overriden by the options passed to the middleware.
|
|
140
333
|
...notUndefinedOptions,
|
|
141
|
-
|
|
334
|
+
// Note that this field is declared after the user's options are spread in,
|
|
335
|
+
// so that this field doesn't get overriden with an un-promisified store!
|
|
336
|
+
store: promisifyStore((_d = notUndefinedOptions.store) != null ? _d : new MemoryStore()),
|
|
337
|
+
// Print an error to the console if a few known misconfigurations are detected.
|
|
338
|
+
validations
|
|
142
339
|
};
|
|
143
|
-
if (typeof config.store.increment !== "function" || typeof config.store.decrement !== "function" || typeof config.store.resetKey !== "function" ||
|
|
340
|
+
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
341
|
throw new TypeError(
|
|
145
342
|
"An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface."
|
|
146
343
|
);
|
|
@@ -155,46 +352,47 @@ var handleAsyncErrors = (fn) => async (request, response, next) => {
|
|
|
155
352
|
}
|
|
156
353
|
};
|
|
157
354
|
var rateLimit = (passedOptions) => {
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
355
|
+
const config = parseOptions(passedOptions != null ? passedOptions : {});
|
|
356
|
+
const options = getOptionsFromConfig(config);
|
|
357
|
+
if (typeof config.store.init === "function")
|
|
358
|
+
config.store.init(options);
|
|
161
359
|
const middleware = handleAsyncErrors(
|
|
162
360
|
async (request, response, next) => {
|
|
163
|
-
const skip = await
|
|
361
|
+
const skip = await config.skip(request, response);
|
|
164
362
|
if (skip) {
|
|
165
363
|
next();
|
|
166
364
|
return;
|
|
167
365
|
}
|
|
168
366
|
const augmentedRequest = request;
|
|
169
|
-
const key = await
|
|
170
|
-
const { totalHits, resetTime } = await
|
|
171
|
-
const retrieveQuota = typeof
|
|
367
|
+
const key = await config.keyGenerator(request, response);
|
|
368
|
+
const { totalHits, resetTime } = await config.store.increment(key);
|
|
369
|
+
const retrieveQuota = typeof config.max === "function" ? config.max(request, response) : config.max;
|
|
172
370
|
const maxHits = await retrieveQuota;
|
|
173
|
-
augmentedRequest[
|
|
371
|
+
augmentedRequest[config.requestPropertyName] = {
|
|
174
372
|
limit: maxHits,
|
|
175
373
|
current: totalHits,
|
|
176
374
|
remaining: Math.max(maxHits - totalHits, 0),
|
|
177
375
|
resetTime
|
|
178
376
|
};
|
|
179
|
-
if (
|
|
377
|
+
if (config.legacyHeaders && !response.headersSent) {
|
|
180
378
|
response.setHeader("X-RateLimit-Limit", maxHits);
|
|
181
379
|
response.setHeader(
|
|
182
380
|
"X-RateLimit-Remaining",
|
|
183
|
-
augmentedRequest[
|
|
381
|
+
augmentedRequest[config.requestPropertyName].remaining
|
|
184
382
|
);
|
|
185
383
|
if (resetTime instanceof Date) {
|
|
186
|
-
response.setHeader("Date", new Date().toUTCString());
|
|
384
|
+
response.setHeader("Date", (/* @__PURE__ */ new Date()).toUTCString());
|
|
187
385
|
response.setHeader(
|
|
188
386
|
"X-RateLimit-Reset",
|
|
189
387
|
Math.ceil(resetTime.getTime() / 1e3)
|
|
190
388
|
);
|
|
191
389
|
}
|
|
192
390
|
}
|
|
193
|
-
if (
|
|
391
|
+
if (config.standardHeaders && !response.headersSent) {
|
|
194
392
|
response.setHeader("RateLimit-Limit", maxHits);
|
|
195
393
|
response.setHeader(
|
|
196
394
|
"RateLimit-Remaining",
|
|
197
|
-
augmentedRequest[
|
|
395
|
+
augmentedRequest[config.requestPropertyName].remaining
|
|
198
396
|
);
|
|
199
397
|
if (resetTime) {
|
|
200
398
|
const deltaSeconds = Math.ceil(
|
|
@@ -203,17 +401,17 @@ var rateLimit = (passedOptions) => {
|
|
|
203
401
|
response.setHeader("RateLimit-Reset", Math.max(0, deltaSeconds));
|
|
204
402
|
}
|
|
205
403
|
}
|
|
206
|
-
if (
|
|
404
|
+
if (config.skipFailedRequests || config.skipSuccessfulRequests) {
|
|
207
405
|
let decremented = false;
|
|
208
406
|
const decrementKey = async () => {
|
|
209
407
|
if (!decremented) {
|
|
210
|
-
await
|
|
408
|
+
await config.store.decrement(key);
|
|
211
409
|
decremented = true;
|
|
212
410
|
}
|
|
213
411
|
};
|
|
214
|
-
if (
|
|
412
|
+
if (config.skipFailedRequests) {
|
|
215
413
|
response.on("finish", async () => {
|
|
216
|
-
if (!
|
|
414
|
+
if (!config.requestWasSuccessful(request, response))
|
|
217
415
|
await decrementKey();
|
|
218
416
|
});
|
|
219
417
|
response.on("close", async () => {
|
|
@@ -224,38 +422,34 @@ var rateLimit = (passedOptions) => {
|
|
|
224
422
|
await decrementKey();
|
|
225
423
|
});
|
|
226
424
|
}
|
|
227
|
-
if (
|
|
425
|
+
if (config.skipSuccessfulRequests) {
|
|
228
426
|
response.on("finish", async () => {
|
|
229
|
-
if (
|
|
427
|
+
if (config.requestWasSuccessful(request, response))
|
|
230
428
|
await decrementKey();
|
|
231
429
|
});
|
|
232
430
|
}
|
|
233
431
|
}
|
|
234
432
|
if (maxHits && totalHits === maxHits + 1) {
|
|
235
|
-
|
|
433
|
+
config.onLimitReached(request, response, options);
|
|
236
434
|
}
|
|
435
|
+
config.validations.disable();
|
|
237
436
|
if (maxHits && totalHits > maxHits) {
|
|
238
|
-
if ((
|
|
239
|
-
response.setHeader("Retry-After", Math.ceil(
|
|
437
|
+
if ((config.legacyHeaders || config.standardHeaders) && !response.headersSent) {
|
|
438
|
+
response.setHeader("Retry-After", Math.ceil(config.windowMs / 1e3));
|
|
240
439
|
}
|
|
241
|
-
|
|
440
|
+
config.handler(request, response, next, options);
|
|
242
441
|
return;
|
|
243
442
|
}
|
|
244
443
|
next();
|
|
245
444
|
}
|
|
246
445
|
);
|
|
247
|
-
middleware.resetKey =
|
|
446
|
+
middleware.resetKey = config.store.resetKey.bind(config.store);
|
|
248
447
|
return middleware;
|
|
249
448
|
};
|
|
250
|
-
var omitUndefinedOptions = (passedOptions) => {
|
|
251
|
-
const omittedOptions = {};
|
|
252
|
-
for (const k of Object.keys(passedOptions)) {
|
|
253
|
-
const key = k;
|
|
254
|
-
if (passedOptions[key] !== void 0) {
|
|
255
|
-
omittedOptions[key] = passedOptions[key];
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
return omittedOptions;
|
|
259
|
-
};
|
|
260
449
|
var lib_default = rateLimit;
|
|
450
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
451
|
+
0 && (module.exports = {
|
|
452
|
+
MemoryStore,
|
|
453
|
+
rateLimit
|
|
454
|
+
});
|
|
261
455
|
module.exports = rateLimit; module.exports.default = rateLimit; module.exports.rateLimit = rateLimit; module.exports.MemoryStore = MemoryStore;
|