express-rate-limit 6.0.1 → 6.0.5
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 +56 -0
- package/dist/index.cjs +226 -0
- package/dist/index.d.ts +248 -0
- package/dist/index.mjs +198 -0
- package/package.json +31 -26
- package/readme.md +50 -27
- package/tsconfig.json +4 -9
- package/dist/cjs/index.d.ts +0 -2
- package/dist/cjs/index.js +0 -19
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/lib.d.ts +0 -15
- package/dist/cjs/lib.js +0 -366
- package/dist/cjs/lib.js.map +0 -1
- package/dist/cjs/memory-store.d.ts +0 -61
- package/dist/cjs/memory-store.js +0 -167
- package/dist/cjs/memory-store.js.map +0 -1
- package/dist/cjs/package.json +0 -12
- package/dist/cjs/types.d.ts +0 -239
- package/dist/cjs/types.js +0 -5
- package/dist/cjs/types.js.map +0 -1
- package/dist/esm/index.d.ts +0 -2
- package/dist/esm/index.js +0 -5
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/lib.d.ts +0 -15
- package/dist/esm/lib.js +0 -361
- package/dist/esm/lib.js.map +0 -1
- package/dist/esm/memory-store.d.ts +0 -61
- package/dist/esm/memory-store.js +0 -165
- package/dist/esm/memory-store.js.map +0 -1
- package/dist/esm/package.json +0 -13
- package/dist/esm/types.d.ts +0 -239
- package/dist/esm/types.js +0 -4
- package/dist/esm/types.js.map +0 -1
package/changelog.md
CHANGED
|
@@ -6,6 +6,62 @@ 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.0.5](https://github.com/nfriedly/express-rate-limit/releases/tag/v6.0.5)
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Use named imports for ExpressJS types so users do not need to enable the
|
|
14
|
+
`esModuleInterop` flag in their Typescript compiler configuration.
|
|
15
|
+
|
|
16
|
+
## [6.0.4](https://github.com/nfriedly/express-rate-limit/releases/tag/v6.0.4)
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- Upload the built package as a `.tgz` to GitHub releases.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- Add ` main` and `module` fields to `package.json`. This helps tools such as
|
|
25
|
+
ESLint that do not yet support the `exports` field.
|
|
26
|
+
- Bumped the minimum node.js version in `package-lock.json` to match
|
|
27
|
+
`package.json`
|
|
28
|
+
|
|
29
|
+
## [6.0.3](https://github.com/nfriedly/express-rate-limit/releases/tag/v6.0.3)
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- Bumped minimum Node version from 12.9 to 14.5 in `package.json` because the
|
|
34
|
+
transpiled output uses the nullish coalescing operator (`??`), which
|
|
35
|
+
[isn't supported in node.js prior to 14.x](https://node.green/#ES2020-features--nullish-coalescing-operator-----).
|
|
36
|
+
|
|
37
|
+
## [6.0.2](https://github.com/nfriedly/express-rate-limit/releases/v6.0.2)
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- Ensure CommonJS projects can import the module.
|
|
42
|
+
|
|
43
|
+
### Added
|
|
44
|
+
|
|
45
|
+
- Add additional tests that test:
|
|
46
|
+
- importing the library in `js-cjs`, `js-esm`, `ts-cjs`, `ts-esm`
|
|
47
|
+
environments.
|
|
48
|
+
- usage of the library with external stores (`redis`, `mongo`, `memcached`,
|
|
49
|
+
`precise`).
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
|
|
53
|
+
- Use [`esbuild`](https://esbuild.github.io/) to generate ESM and CJS output.
|
|
54
|
+
This reduces the size of the built package from 138 kb to 13kb and build time
|
|
55
|
+
to 4 ms! :rocket:
|
|
56
|
+
- Use [`dts-bundle-generator`](https://github.com/timocov/dts-bundle-generator)
|
|
57
|
+
to generate a single Typescript declaration file.
|
|
58
|
+
|
|
59
|
+
## [6.0.1](https://github.com/nfriedly/express-rate-limit/releases/v6.0.1)
|
|
60
|
+
|
|
61
|
+
### Fixed
|
|
62
|
+
|
|
63
|
+
- Ensure CommonJS projects can import the module.
|
|
64
|
+
|
|
9
65
|
## [6.0.0](https://github.com/nfriedly/express-rate-limit/releases/v6.0.0)
|
|
10
66
|
|
|
11
67
|
### Added
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __reExport = (target, module2, copyDefault, desc) => {
|
|
11
|
+
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(module2))
|
|
13
|
+
if (!__hasOwnProp.call(target, key) && (copyDefault || key !== "default"))
|
|
14
|
+
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return target;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = /* @__PURE__ */ ((cache) => {
|
|
19
|
+
return (module2, temp) => {
|
|
20
|
+
return cache && cache.get(module2) || (temp = __reExport(__markAsModule({}), module2, 1), cache && cache.set(module2, temp), temp);
|
|
21
|
+
};
|
|
22
|
+
})(typeof WeakMap !== "undefined" ? /* @__PURE__ */ new WeakMap() : 0);
|
|
23
|
+
|
|
24
|
+
// source/index.ts
|
|
25
|
+
var source_exports = {};
|
|
26
|
+
__export(source_exports, {
|
|
27
|
+
default: () => source_default
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// source/memory-store.ts
|
|
31
|
+
var calculateNextResetTime = (windowMs) => {
|
|
32
|
+
const resetTime = new Date();
|
|
33
|
+
resetTime.setMilliseconds(resetTime.getMilliseconds() + windowMs);
|
|
34
|
+
return resetTime;
|
|
35
|
+
};
|
|
36
|
+
var MemoryStore = class {
|
|
37
|
+
init(options) {
|
|
38
|
+
this.windowMs = options.windowMs;
|
|
39
|
+
this.resetTime = calculateNextResetTime(this.windowMs);
|
|
40
|
+
this.hits = {};
|
|
41
|
+
const interval = setInterval(async () => {
|
|
42
|
+
await this.resetAll();
|
|
43
|
+
}, this.windowMs);
|
|
44
|
+
if (interval.unref) {
|
|
45
|
+
interval.unref();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async increment(key) {
|
|
49
|
+
const totalHits = (this.hits[key] ?? 0) + 1;
|
|
50
|
+
this.hits[key] = totalHits;
|
|
51
|
+
return {
|
|
52
|
+
totalHits,
|
|
53
|
+
resetTime: this.resetTime
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
async decrement(key) {
|
|
57
|
+
const current = this.hits[key];
|
|
58
|
+
if (current) {
|
|
59
|
+
this.hits[key] = current - 1;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async resetKey(key) {
|
|
63
|
+
delete this.hits[key];
|
|
64
|
+
}
|
|
65
|
+
async resetAll() {
|
|
66
|
+
this.hits = {};
|
|
67
|
+
this.resetTime = calculateNextResetTime(this.windowMs);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// source/lib.ts
|
|
72
|
+
var isLegacyStore = (store) => typeof store.incr === "function" && typeof store.increment !== "function";
|
|
73
|
+
var promisifyStore = (passedStore) => {
|
|
74
|
+
if (!isLegacyStore(passedStore)) {
|
|
75
|
+
return passedStore;
|
|
76
|
+
}
|
|
77
|
+
const legacyStore = passedStore;
|
|
78
|
+
class PromisifiedStore {
|
|
79
|
+
async increment(key) {
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
81
|
+
legacyStore.incr(key, (error, totalHits, resetTime) => {
|
|
82
|
+
if (error)
|
|
83
|
+
reject(error);
|
|
84
|
+
resolve({ totalHits, resetTime });
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
async decrement(key) {
|
|
89
|
+
return Promise.resolve(legacyStore.decrement(key));
|
|
90
|
+
}
|
|
91
|
+
async resetKey(key) {
|
|
92
|
+
return Promise.resolve(legacyStore.resetKey(key));
|
|
93
|
+
}
|
|
94
|
+
async resetAll() {
|
|
95
|
+
if (typeof legacyStore.resetAll === "function")
|
|
96
|
+
return Promise.resolve(legacyStore.resetAll());
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return new PromisifiedStore();
|
|
100
|
+
};
|
|
101
|
+
var parseOptions = (passedOptions) => {
|
|
102
|
+
const options = {
|
|
103
|
+
windowMs: 60 * 1e3,
|
|
104
|
+
store: new MemoryStore(),
|
|
105
|
+
max: 5,
|
|
106
|
+
message: "Too many requests, please try again later.",
|
|
107
|
+
statusCode: 429,
|
|
108
|
+
legacyHeaders: passedOptions.headers ?? true,
|
|
109
|
+
standardHeaders: passedOptions.draft_polli_ratelimit_headers ?? false,
|
|
110
|
+
requestPropertyName: "rateLimit",
|
|
111
|
+
skipFailedRequests: false,
|
|
112
|
+
skipSuccessfulRequests: false,
|
|
113
|
+
requestWasSuccessful: (_request, response) => response.statusCode < 400,
|
|
114
|
+
skip: (_request, _response) => false,
|
|
115
|
+
keyGenerator: (request, _response) => {
|
|
116
|
+
if (!request.ip) {
|
|
117
|
+
console.error("WARN | `express-rate-limit` | `request.ip` is undefined. You can avoid this by providing a custom `keyGenerator` function, but it may be indicative of a larger issue.");
|
|
118
|
+
}
|
|
119
|
+
return request.ip;
|
|
120
|
+
},
|
|
121
|
+
handler: (_request, response, _next, _optionsUsed) => {
|
|
122
|
+
response.status(options.statusCode).send(options.message);
|
|
123
|
+
},
|
|
124
|
+
onLimitReached: (_request, _response, _optionsUsed) => {
|
|
125
|
+
},
|
|
126
|
+
...passedOptions
|
|
127
|
+
};
|
|
128
|
+
if (typeof options.store.incr !== "function" && typeof options.store.increment !== "function" || typeof options.store.decrement !== "function" || typeof options.store.resetKey !== "function" || typeof options.store.resetAll !== "undefined" && typeof options.store.resetAll !== "function" || typeof options.store.init !== "undefined" && typeof options.store.init !== "function") {
|
|
129
|
+
throw new TypeError("An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface.");
|
|
130
|
+
}
|
|
131
|
+
options.store = promisifyStore(options.store);
|
|
132
|
+
return options;
|
|
133
|
+
};
|
|
134
|
+
var handleAsyncErrors = (fn) => async (request, response, next) => {
|
|
135
|
+
try {
|
|
136
|
+
await Promise.resolve(fn(request, response, next)).catch(next);
|
|
137
|
+
} catch (error) {
|
|
138
|
+
next(error);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
var rateLimit = (passedOptions) => {
|
|
142
|
+
const options = parseOptions(passedOptions ?? {});
|
|
143
|
+
if (typeof options.store.init === "function")
|
|
144
|
+
options.store.init(options);
|
|
145
|
+
const middleware = handleAsyncErrors(async (request, response, next) => {
|
|
146
|
+
const skip = await options.skip(request, response);
|
|
147
|
+
if (skip) {
|
|
148
|
+
next();
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const augmentedRequest = request;
|
|
152
|
+
const key = await options.keyGenerator(request, response);
|
|
153
|
+
const { totalHits, resetTime } = await options.store.increment(key);
|
|
154
|
+
const retrieveQuota = typeof options.max === "function" ? options.max(request, response) : options.max;
|
|
155
|
+
const maxHits = await retrieveQuota;
|
|
156
|
+
augmentedRequest[options.requestPropertyName] = {
|
|
157
|
+
limit: maxHits,
|
|
158
|
+
current: totalHits,
|
|
159
|
+
remaining: Math.max(maxHits - totalHits, 0),
|
|
160
|
+
resetTime
|
|
161
|
+
};
|
|
162
|
+
if (options.legacyHeaders && !response.headersSent) {
|
|
163
|
+
response.setHeader("X-RateLimit-Limit", maxHits);
|
|
164
|
+
response.setHeader("X-RateLimit-Remaining", augmentedRequest[options.requestPropertyName].remaining);
|
|
165
|
+
if (resetTime instanceof Date) {
|
|
166
|
+
response.setHeader("Date", new Date().toUTCString());
|
|
167
|
+
response.setHeader("X-RateLimit-Reset", Math.ceil(resetTime.getTime() / 1e3));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (options.standardHeaders && !response.headersSent) {
|
|
171
|
+
response.setHeader("RateLimit-Limit", maxHits);
|
|
172
|
+
response.setHeader("RateLimit-Remaining", augmentedRequest[options.requestPropertyName].remaining);
|
|
173
|
+
if (resetTime) {
|
|
174
|
+
const deltaSeconds = Math.ceil((resetTime.getTime() - Date.now()) / 1e3);
|
|
175
|
+
response.setHeader("RateLimit-Reset", Math.max(0, deltaSeconds));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (options.skipFailedRequests || options.skipSuccessfulRequests) {
|
|
179
|
+
let decremented = false;
|
|
180
|
+
const decrementKey = async () => {
|
|
181
|
+
if (!decremented) {
|
|
182
|
+
await options.store.decrement(key);
|
|
183
|
+
decremented = true;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
if (options.skipFailedRequests) {
|
|
187
|
+
response.on("finish", async () => {
|
|
188
|
+
if (!options.requestWasSuccessful(request, response))
|
|
189
|
+
await decrementKey();
|
|
190
|
+
});
|
|
191
|
+
response.on("close", async () => {
|
|
192
|
+
if (!response.writableEnded)
|
|
193
|
+
await decrementKey();
|
|
194
|
+
});
|
|
195
|
+
response.on("error", async () => {
|
|
196
|
+
await decrementKey();
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
if (options.skipSuccessfulRequests) {
|
|
200
|
+
response.on("finish", async () => {
|
|
201
|
+
if (options.requestWasSuccessful(request, response))
|
|
202
|
+
await decrementKey();
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (maxHits && totalHits === maxHits + 1) {
|
|
207
|
+
options.onLimitReached(request, response, options);
|
|
208
|
+
}
|
|
209
|
+
if (maxHits && totalHits > maxHits) {
|
|
210
|
+
if ((options.legacyHeaders || options.standardHeaders) && !response.headersSent) {
|
|
211
|
+
response.setHeader("Retry-After", Math.ceil(options.windowMs / 1e3));
|
|
212
|
+
}
|
|
213
|
+
options.handler(request, response, next, options);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
next();
|
|
217
|
+
});
|
|
218
|
+
middleware.resetKey = options.store.resetKey.bind(options.store);
|
|
219
|
+
return middleware;
|
|
220
|
+
};
|
|
221
|
+
var lib_default = rateLimit;
|
|
222
|
+
|
|
223
|
+
// source/index.ts
|
|
224
|
+
var source_default = lib_default;
|
|
225
|
+
module.exports = __toCommonJS(source_exports);
|
|
226
|
+
module.exports = rateLimit;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
// Generated by dts-bundle-generator v6.3.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 declare 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 declare 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 declare 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 declare 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 declare 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 declare 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 interface 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 interface 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
|
+
/**
|
|
131
|
+
* The configuration options for the rate limiter.
|
|
132
|
+
*/
|
|
133
|
+
export interface Options {
|
|
134
|
+
/**
|
|
135
|
+
* How long we should remember the requests.
|
|
136
|
+
*/
|
|
137
|
+
readonly windowMs: number;
|
|
138
|
+
/**
|
|
139
|
+
* The maximum number of connection to allow during the `window` before
|
|
140
|
+
* rate limiting the client.
|
|
141
|
+
*
|
|
142
|
+
* Can be the limit itself as a number or express middleware that parses
|
|
143
|
+
* the request and then figures out the limit.
|
|
144
|
+
*/
|
|
145
|
+
readonly max: number | ValueDeterminingMiddleware<number>;
|
|
146
|
+
/**
|
|
147
|
+
* The response body to send back when a client is rate limited.
|
|
148
|
+
*/
|
|
149
|
+
readonly message: any;
|
|
150
|
+
/**
|
|
151
|
+
* The HTTP status code to send back when a client is rate limited.
|
|
152
|
+
*
|
|
153
|
+
* Defaults to `HTTP 429 Too Many Requests` (RFC 6585).
|
|
154
|
+
*/
|
|
155
|
+
readonly statusCode: number;
|
|
156
|
+
/**
|
|
157
|
+
* Whether to send `X-RateLimit-*` headers with the rate limit and the number
|
|
158
|
+
* of requests.
|
|
159
|
+
*/
|
|
160
|
+
readonly legacyHeaders: boolean;
|
|
161
|
+
/**
|
|
162
|
+
* Whether to enable support for the rate limit standardization headers (`RateLimit-*`).
|
|
163
|
+
*/
|
|
164
|
+
readonly standardHeaders: boolean;
|
|
165
|
+
/**
|
|
166
|
+
* The name of the property on the request object to store the rate limit info.
|
|
167
|
+
*
|
|
168
|
+
* Defaults to `rateLimit`.
|
|
169
|
+
*/
|
|
170
|
+
readonly requestPropertyName: string;
|
|
171
|
+
/**
|
|
172
|
+
* If `true`, the library will (by default) skip all requests that have a 4XX
|
|
173
|
+
* or 5XX status.
|
|
174
|
+
*/
|
|
175
|
+
readonly skipFailedRequests: boolean;
|
|
176
|
+
/**
|
|
177
|
+
* If `true`, the library will (by default) skip all requests that have a
|
|
178
|
+
* status code less than 400.
|
|
179
|
+
*/
|
|
180
|
+
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
|
+
/**
|
|
187
|
+
* Method to generate custom identifiers for clients.
|
|
188
|
+
*
|
|
189
|
+
* By default, the client's IP address is used.
|
|
190
|
+
*/
|
|
191
|
+
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
|
+
/**
|
|
198
|
+
* Express request handler that sends back a response when a client is
|
|
199
|
+
* rate-limited.
|
|
200
|
+
*/
|
|
201
|
+
readonly handler: RateLimitExceededEventHandler;
|
|
202
|
+
/**
|
|
203
|
+
* Express request handler that sends back a response when a client has
|
|
204
|
+
* reached their rate limit, and will be rate limited on their next request.
|
|
205
|
+
*/
|
|
206
|
+
readonly onLimitReached: RateLimitReachedEventHandler;
|
|
207
|
+
/**
|
|
208
|
+
* The {@link Store} to use to store the hit count for each client.
|
|
209
|
+
*/
|
|
210
|
+
store: Store;
|
|
211
|
+
/**
|
|
212
|
+
* Whether to send `X-RateLimit-*` headers with the rate limit and the number
|
|
213
|
+
* of requests.
|
|
214
|
+
*
|
|
215
|
+
* @deprecated 6.x - This option was renamed to `legacyHeaders`.
|
|
216
|
+
*/
|
|
217
|
+
headers?: boolean;
|
|
218
|
+
/**
|
|
219
|
+
* Whether to send `RateLimit-*` headers with the rate limit and the number
|
|
220
|
+
* of requests.
|
|
221
|
+
*
|
|
222
|
+
* @deprecated 6.x - This option was renamed to `standardHeaders`.
|
|
223
|
+
*/
|
|
224
|
+
draft_polli_ratelimit_headers?: boolean;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* The extended request object that includes information about the client's
|
|
228
|
+
* rate limit.
|
|
229
|
+
*/
|
|
230
|
+
export declare type AugmentedRequest = Request & {
|
|
231
|
+
[key: string]: RateLimitInfo;
|
|
232
|
+
};
|
|
233
|
+
/**
|
|
234
|
+
* The rate limit related information for each client included in the
|
|
235
|
+
* Express request object.
|
|
236
|
+
*/
|
|
237
|
+
export interface RateLimitInfo {
|
|
238
|
+
readonly limit: number;
|
|
239
|
+
readonly current: number;
|
|
240
|
+
readonly remaining: number;
|
|
241
|
+
readonly resetTime: Date | undefined;
|
|
242
|
+
}
|
|
243
|
+
declare const rateLimit: (passedOptions?: (Omit<Partial<Options>, "store"> & {
|
|
244
|
+
store?: LegacyStore | Store | undefined;
|
|
245
|
+
}) | undefined) => RateLimitRequestHandler;
|
|
246
|
+
export default rateLimit;
|
|
247
|
+
|
|
248
|
+
export {};
|