express-rate-limit 6.0.0 → 6.0.4
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 +40 -2
- package/dist/index.cjs +226 -0
- package/dist/index.d.ts +248 -0
- package/dist/index.mjs +198 -0
- package/package.json +27 -37
- package/readme.md +89 -28
- package/tsconfig.json +1 -4
- 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/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/types.d.ts +0 -239
- package/dist/esm/types.js +0 -4
- package/dist/esm/types.js.map +0 -1
package/dist/esm/lib.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"lib.js","sourceRoot":"","sources":["../../source/lib.ts"],"names":[],"mappings":"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","sourcesContent":["// /source/lib.ts\n// The option parser and rate limiting middleware\n\nimport Express from 'express'\n\nimport {\n\tOptions,\n\tAugmentedRequest,\n\tRateLimitRequestHandler,\n\tLegacyStore,\n\tStore,\n\tIncrementResponse,\n} from './types.js'\nimport MemoryStore from './memory-store.js'\n\n/**\n * Type guard to check if a store is legacy store.\n *\n * @param store {LegacyStore | Store} - The store to check\n *\n * @return {boolean} - Whether the store is a legacy store\n */\nconst isLegacyStore = (store: LegacyStore | Store): store is LegacyStore =>\n\t// Check that `incr` exists but `increment` does not - store authors might want\n\t// to keep both around for backwards compatibility.\n\ttypeof (store as any).incr === 'function' &&\n\ttypeof (store as any).increment !== 'function'\n\n/**\n * Converts a legacy store to the promisified version.\n *\n * @param store {LegacyStore | Store} - The legacy store or even a modern store\n *\n * @returns {Store} - The promisified version of the store\n */\nconst promisifyStore = (passedStore: LegacyStore | Store): Store => {\n\tif (!isLegacyStore(passedStore)) {\n\t\t// It's not an old store, return as is\n\t\treturn passedStore\n\t}\n\n\t// Why can't Typescript understand this?\n\tconst legacyStore = passedStore\n\n\t// A promisified version of the store\n\tclass PromisifiedStore implements Store {\n\t\tasync increment(key: string): Promise<IncrementResponse> {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tlegacyStore.incr(\n\t\t\t\t\tkey,\n\t\t\t\t\t(\n\t\t\t\t\t\terror: Error | undefined,\n\t\t\t\t\t\ttotalHits: number,\n\t\t\t\t\t\tresetTime: Date | undefined,\n\t\t\t\t\t) => {\n\t\t\t\t\t\tif (error) reject(error)\n\t\t\t\t\t\tresolve({ totalHits, resetTime })\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t})\n\t\t}\n\n\t\tasync decrement(key: string): Promise<void> {\n\t\t\treturn Promise.resolve(legacyStore.decrement(key))\n\t\t}\n\n\t\tasync resetKey(key: string): Promise<void> {\n\t\t\treturn Promise.resolve(legacyStore.resetKey(key))\n\t\t}\n\n\t\tasync resetAll(): Promise<void> {\n\t\t\tif (typeof legacyStore.resetAll === 'function')\n\t\t\t\treturn Promise.resolve(legacyStore.resetAll())\n\t\t}\n\t}\n\n\treturn new PromisifiedStore()\n}\n\n/**\n * Adds the defaults for options the user has not specified.\n *\n * @param options {Options} - The options the user specifies\n *\n * @returns {Options} - A complete configuration object\n */\nconst parseOptions = (\n\tpassedOptions: Omit<Partial<Options>, 'store'> & {\n\t\tstore?: Store | LegacyStore\n\t},\n): Options => {\n\t// Now add the defaults for the other options\n\n\tconst options = {\n\t\twindowMs: 60 * 1000,\n\t\tstore: new MemoryStore(),\n\t\tmax: 5,\n\t\tmessage: 'Too many requests, please try again later.',\n\t\tstatusCode: 429,\n\t\tlegacyHeaders: passedOptions.headers ?? true,\n\t\tstandardHeaders: passedOptions.draft_polli_ratelimit_headers ?? false,\n\t\trequestPropertyName: 'rateLimit',\n\t\tskipFailedRequests: false,\n\t\tskipSuccessfulRequests: false,\n\t\trequestWasSuccessful: (\n\t\t\t_request: Express.Request,\n\t\t\tresponse: Express.Response,\n\t\t): boolean => response.statusCode < 400,\n\t\tskip: (_request: Express.Request, _response: Express.Response): boolean =>\n\t\t\tfalse,\n\t\tkeyGenerator: (\n\t\t\trequest: Express.Request,\n\t\t\t_response: Express.Response,\n\t\t): string => {\n\t\t\tif (!request.ip) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t'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.',\n\t\t\t\t)\n\t\t\t}\n\n\t\t\treturn request.ip\n\t\t},\n\t\thandler: (\n\t\t\t_request: Express.Request,\n\t\t\tresponse: Express.Response,\n\t\t\t_next: Express.NextFunction,\n\t\t\t_optionsUsed: Options,\n\t\t): void => {\n\t\t\tresponse.status(options.statusCode).send(options.message)\n\t\t},\n\t\tonLimitReached: (\n\t\t\t_request: Express.Request,\n\t\t\t_response: Express.Response,\n\t\t\t_optionsUsed: Options,\n\t\t): void => {},\n\t\t...passedOptions,\n\t}\n\n\t// Ensure that the store passed implements the either the `Store` or `LegacyStore`\n\t// interface\n\tif (\n\t\t(typeof (options.store as LegacyStore).incr !== 'function' &&\n\t\t\ttypeof (options.store as Store).increment !== 'function') ||\n\t\ttypeof options.store.decrement !== 'function' ||\n\t\ttypeof options.store.resetKey !== 'function' ||\n\t\t(typeof options.store.resetAll !== 'undefined' &&\n\t\t\ttypeof options.store.resetAll !== 'function') ||\n\t\t(typeof (options.store as Store).init !== 'undefined' &&\n\t\t\ttypeof (options.store as Store).init !== 'function')\n\t) {\n\t\tthrow new TypeError(\n\t\t\t'An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface.',\n\t\t)\n\t}\n\n\t// Promisify the store, if it is not already\n\toptions.store = promisifyStore(options.store)\n\n\t// Return the 'clean' options\n\treturn options as Options\n}\n\n/**\n * Just pass on any errors for the developer to handle, usually as a HTTP 500\n * Internal Server Error.\n *\n * @param fn {Express.RequestHandler} - The request handler for which to handle errors\n *\n * @returns {Express.RequestHandler} - The request handler wrapped with a `.catch` clause\n *\n * @private\n */\nconst handleAsyncErrors =\n\t(fn: Express.RequestHandler): Express.RequestHandler =>\n\tasync (\n\t\trequest: Express.Request,\n\t\tresponse: Express.Response,\n\t\tnext: Express.NextFunction,\n\t) => {\n\t\ttry {\n\t\t\tawait Promise.resolve(fn(request, response, next)).catch(next)\n\t\t} catch (error: unknown) {\n\t\t\tnext(error)\n\t\t}\n\t}\n\n/**\n *\n * Create an instance of IP rate-limiting middleware for Express.\n *\n * @param passedOptions {Options} - Options to configure the rate limiter\n *\n * @returns {RateLimitRequestHandler} - The middleware that rate-limits clients based on your configuration\n *\n * @public\n */\nconst rateLimit = (\n\tpassedOptions?: Omit<Partial<Options>, 'store'> & {\n\t\tstore?: Store | LegacyStore\n\t},\n): RateLimitRequestHandler => {\n\t// Parse the options and add the default values for unspecified options\n\tconst options = parseOptions(passedOptions ?? {})\n\t// Call the `init` method on the store, if it exists\n\tif (typeof options.store.init === 'function') options.store.init(options)\n\n\t// Then return the actual middleware\n\tconst middleware = handleAsyncErrors(\n\t\tasync (\n\t\t\trequest: Express.Request,\n\t\t\tresponse: Express.Response,\n\t\t\tnext: Express.NextFunction,\n\t\t) => {\n\t\t\t// First check if we should skip the request\n\t\t\tconst skip = await options.skip(request, response)\n\t\t\tif (skip) {\n\t\t\t\tnext()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Create an augmented request\n\t\t\tconst augmentedRequest = request as AugmentedRequest\n\n\t\t\t// Get a unique key for the client\n\t\t\tconst key = await options.keyGenerator(request, response)\n\t\t\t// Increment the client's hit counter by one\n\t\t\tconst { totalHits, resetTime } = await options.store.increment(key)\n\n\t\t\t// Get the quota (max number of hits) for each client\n\t\t\tconst retrieveQuota =\n\t\t\t\ttypeof options.max === 'function'\n\t\t\t\t\t? options.max(request, response)\n\t\t\t\t\t: options.max\n\n\t\t\tconst maxHits = await retrieveQuota\n\t\t\t// Set the rate limit information on the augmented request object\n\t\t\taugmentedRequest[options.requestPropertyName] = {\n\t\t\t\tlimit: maxHits,\n\t\t\t\tcurrent: totalHits,\n\t\t\t\tremaining: Math.max(maxHits - totalHits, 0),\n\t\t\t\tresetTime,\n\t\t\t}\n\n\t\t\t// Set the X-RateLimit headers on the response object if enabled\n\t\t\tif (options.legacyHeaders && !response.headersSent) {\n\t\t\t\tresponse.setHeader('X-RateLimit-Limit', maxHits)\n\t\t\t\tresponse.setHeader(\n\t\t\t\t\t'X-RateLimit-Remaining',\n\t\t\t\t\taugmentedRequest[options.requestPropertyName].remaining,\n\t\t\t\t)\n\n\t\t\t\t// If we have a resetTime, also provide the current date to help avoid issues with incorrect clocks\n\t\t\t\tif (resetTime instanceof Date) {\n\t\t\t\t\tresponse.setHeader('Date', new Date().toUTCString())\n\t\t\t\t\tresponse.setHeader(\n\t\t\t\t\t\t'X-RateLimit-Reset',\n\t\t\t\t\t\tMath.ceil(resetTime.getTime() / 1000),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the standardized RateLimit headers on the response object\n\t\t\t// if enabled\n\t\t\tif (options.standardHeaders && !response.headersSent) {\n\t\t\t\tresponse.setHeader('RateLimit-Limit', maxHits)\n\t\t\t\tresponse.setHeader(\n\t\t\t\t\t'RateLimit-Remaining',\n\t\t\t\t\taugmentedRequest[options.requestPropertyName].remaining,\n\t\t\t\t)\n\n\t\t\t\tif (resetTime) {\n\t\t\t\t\tconst deltaSeconds = Math.ceil(\n\t\t\t\t\t\t(resetTime.getTime() - Date.now()) / 1000,\n\t\t\t\t\t)\n\t\t\t\t\tresponse.setHeader('RateLimit-Reset', Math.max(0, deltaSeconds))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If we are to skip failed/successfull requests, decrement the\n\t\t\t// counter accordingly once we know the status code of the request\n\t\t\tif (options.skipFailedRequests || options.skipSuccessfulRequests) {\n\t\t\t\tlet decremented = false\n\t\t\t\tconst decrementKey = async () => {\n\t\t\t\t\tif (!decremented) {\n\t\t\t\t\t\tawait options.store.decrement(key)\n\t\t\t\t\t\tdecremented = true\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (options.skipFailedRequests) {\n\t\t\t\t\tresponse.on('finish', async () => {\n\t\t\t\t\t\tif (!options.requestWasSuccessful(request, response))\n\t\t\t\t\t\t\tawait decrementKey()\n\t\t\t\t\t})\n\t\t\t\t\tresponse.on('close', async () => {\n\t\t\t\t\t\tif (!response.writableEnded) await decrementKey()\n\t\t\t\t\t})\n\t\t\t\t\tresponse.on('error', async () => {\n\t\t\t\t\t\tawait decrementKey()\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tif (options.skipSuccessfulRequests) {\n\t\t\t\t\tresponse.on('finish', async () => {\n\t\t\t\t\t\tif (options.requestWasSuccessful(request, response))\n\t\t\t\t\t\t\tawait decrementKey()\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Call the {@link Options.onLimitReached} callback on\n\t\t\t// the first request where client exceeds their rate limit.\n\t\t\tif (maxHits && totalHits === maxHits + 1) {\n\t\t\t\toptions.onLimitReached(request, response, options)\n\t\t\t}\n\n\t\t\t// If the client has exceeded their rate limit, set the Retry-After\n\t\t\t// header and call the {@link Options.handler} function\n\t\t\tif (maxHits && totalHits > maxHits) {\n\t\t\t\tif (\n\t\t\t\t\t(options.legacyHeaders || options.standardHeaders) &&\n\t\t\t\t\t!response.headersSent\n\t\t\t\t) {\n\t\t\t\t\tresponse.setHeader('Retry-After', Math.ceil(options.windowMs / 1000))\n\t\t\t\t}\n\n\t\t\t\toptions.handler(request, response, next, options)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tnext()\n\t\t},\n\t)\n\n\t// Export the store's function to reset the hit counter for a particular\n\t// client based on their identifier\n\t;(middleware as RateLimitRequestHandler).resetKey =\n\t\toptions.store.resetKey.bind(options.store)\n\n\treturn middleware as RateLimitRequestHandler\n}\n\n// Export it to the world!\nexport default rateLimit\n"]}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { Store, Options, IncrementResponse } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* A {@link Store} that stores the hit count for each client in
|
|
4
|
-
* memory.
|
|
5
|
-
*
|
|
6
|
-
* @public
|
|
7
|
-
*/
|
|
8
|
-
export default class MemoryStore implements Store {
|
|
9
|
-
/**
|
|
10
|
-
* The duration of time before which all hit counts are reset (in milliseconds).
|
|
11
|
-
*/
|
|
12
|
-
windowMs: number;
|
|
13
|
-
/**
|
|
14
|
-
* The map that stores the number of hits for each client in memory.
|
|
15
|
-
*/
|
|
16
|
-
hits: {
|
|
17
|
-
[key: string]: number | undefined;
|
|
18
|
-
};
|
|
19
|
-
/**
|
|
20
|
-
* The time at which all hit counts will be reset.
|
|
21
|
-
*/
|
|
22
|
-
resetTime: Date;
|
|
23
|
-
/**
|
|
24
|
-
* Method that initializes the store.
|
|
25
|
-
*
|
|
26
|
-
* @param options {Options} - The options used to setup the middleware
|
|
27
|
-
*/
|
|
28
|
-
init(options: Options): void;
|
|
29
|
-
/**
|
|
30
|
-
* Method to increment a client's hit counter.
|
|
31
|
-
*
|
|
32
|
-
* @param key {string} - The identifier for a client
|
|
33
|
-
*
|
|
34
|
-
* @returns {IncrementResponse} - The number of hits and reset time for that client
|
|
35
|
-
*
|
|
36
|
-
* @public
|
|
37
|
-
*/
|
|
38
|
-
increment(key: string): Promise<IncrementResponse>;
|
|
39
|
-
/**
|
|
40
|
-
* Method to decrement a client's hit counter.
|
|
41
|
-
*
|
|
42
|
-
* @param key {string} - The identifier for a client
|
|
43
|
-
*
|
|
44
|
-
* @public
|
|
45
|
-
*/
|
|
46
|
-
decrement(key: string): Promise<void>;
|
|
47
|
-
/**
|
|
48
|
-
* Method to reset a client's hit counter.
|
|
49
|
-
*
|
|
50
|
-
* @param key {string} - The identifier for a client
|
|
51
|
-
*
|
|
52
|
-
* @public
|
|
53
|
-
*/
|
|
54
|
-
resetKey(key: string): Promise<void>;
|
|
55
|
-
/**
|
|
56
|
-
* Method to reset everyone's hit counter.
|
|
57
|
-
*
|
|
58
|
-
* @public
|
|
59
|
-
*/
|
|
60
|
-
resetAll(): Promise<void>;
|
|
61
|
-
}
|
package/dist/esm/memory-store.js
DELETED
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
// /source/memory-store.ts
|
|
2
|
-
// A memory store for hit counts
|
|
3
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
5
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
6
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
7
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
8
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
9
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
|
-
});
|
|
11
|
-
};
|
|
12
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
13
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
14
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
15
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
16
|
-
function step(op) {
|
|
17
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
18
|
-
while (_) try {
|
|
19
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
20
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
21
|
-
switch (op[0]) {
|
|
22
|
-
case 0: case 1: t = op; break;
|
|
23
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
24
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
25
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
26
|
-
default:
|
|
27
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
28
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
29
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
30
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
31
|
-
if (t[2]) _.ops.pop();
|
|
32
|
-
_.trys.pop(); continue;
|
|
33
|
-
}
|
|
34
|
-
op = body.call(thisArg, _);
|
|
35
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
36
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
/**
|
|
40
|
-
* Calculates the time when all hit counters will be reset.
|
|
41
|
-
*
|
|
42
|
-
* @param windowMs {number} - The duration of a window (in milliseconds)
|
|
43
|
-
*
|
|
44
|
-
* @returns {Date}
|
|
45
|
-
*
|
|
46
|
-
* @private
|
|
47
|
-
*/
|
|
48
|
-
var calculateNextResetTime = function (windowMs) {
|
|
49
|
-
var resetTime = new Date();
|
|
50
|
-
resetTime.setMilliseconds(resetTime.getMilliseconds() + windowMs);
|
|
51
|
-
return resetTime;
|
|
52
|
-
};
|
|
53
|
-
/**
|
|
54
|
-
* A {@link Store} that stores the hit count for each client in
|
|
55
|
-
* memory.
|
|
56
|
-
*
|
|
57
|
-
* @public
|
|
58
|
-
*/
|
|
59
|
-
var MemoryStore = /** @class */ (function () {
|
|
60
|
-
function MemoryStore() {
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Method that initializes the store.
|
|
64
|
-
*
|
|
65
|
-
* @param options {Options} - The options used to setup the middleware
|
|
66
|
-
*/
|
|
67
|
-
MemoryStore.prototype.init = function (options) {
|
|
68
|
-
var _this = this;
|
|
69
|
-
// Get the duration of a window from the options
|
|
70
|
-
this.windowMs = options.windowMs;
|
|
71
|
-
// Then calculate the reset time using that
|
|
72
|
-
this.resetTime = calculateNextResetTime(this.windowMs);
|
|
73
|
-
// Initialise the hit counter map
|
|
74
|
-
this.hits = {};
|
|
75
|
-
// Reset hit counts for ALL clients every `windowMs` - this will also
|
|
76
|
-
// re-calculate the `resetTime`
|
|
77
|
-
var interval = setInterval(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
78
|
-
return __generator(this, function (_a) {
|
|
79
|
-
switch (_a.label) {
|
|
80
|
-
case 0: return [4 /*yield*/, this.resetAll()];
|
|
81
|
-
case 1:
|
|
82
|
-
_a.sent();
|
|
83
|
-
return [2 /*return*/];
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
}); }, this.windowMs);
|
|
87
|
-
if (interval.unref) {
|
|
88
|
-
interval.unref();
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
/**
|
|
92
|
-
* Method to increment a client's hit counter.
|
|
93
|
-
*
|
|
94
|
-
* @param key {string} - The identifier for a client
|
|
95
|
-
*
|
|
96
|
-
* @returns {IncrementResponse} - The number of hits and reset time for that client
|
|
97
|
-
*
|
|
98
|
-
* @public
|
|
99
|
-
*/
|
|
100
|
-
MemoryStore.prototype.increment = function (key) {
|
|
101
|
-
var _a;
|
|
102
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
103
|
-
var totalHits;
|
|
104
|
-
return __generator(this, function (_b) {
|
|
105
|
-
totalHits = ((_a = this.hits[key]) !== null && _a !== void 0 ? _a : 0) + 1;
|
|
106
|
-
this.hits[key] = totalHits;
|
|
107
|
-
return [2 /*return*/, {
|
|
108
|
-
totalHits: totalHits,
|
|
109
|
-
resetTime: this.resetTime
|
|
110
|
-
}];
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
};
|
|
114
|
-
/**
|
|
115
|
-
* Method to decrement a client's hit counter.
|
|
116
|
-
*
|
|
117
|
-
* @param key {string} - The identifier for a client
|
|
118
|
-
*
|
|
119
|
-
* @public
|
|
120
|
-
*/
|
|
121
|
-
MemoryStore.prototype.decrement = function (key) {
|
|
122
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
123
|
-
var current;
|
|
124
|
-
return __generator(this, function (_a) {
|
|
125
|
-
current = this.hits[key];
|
|
126
|
-
if (current) {
|
|
127
|
-
this.hits[key] = current - 1;
|
|
128
|
-
}
|
|
129
|
-
return [2 /*return*/];
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
};
|
|
133
|
-
/**
|
|
134
|
-
* Method to reset a client's hit counter.
|
|
135
|
-
*
|
|
136
|
-
* @param key {string} - The identifier for a client
|
|
137
|
-
*
|
|
138
|
-
* @public
|
|
139
|
-
*/
|
|
140
|
-
MemoryStore.prototype.resetKey = function (key) {
|
|
141
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
142
|
-
return __generator(this, function (_a) {
|
|
143
|
-
delete this.hits[key];
|
|
144
|
-
return [2 /*return*/];
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
};
|
|
148
|
-
/**
|
|
149
|
-
* Method to reset everyone's hit counter.
|
|
150
|
-
*
|
|
151
|
-
* @public
|
|
152
|
-
*/
|
|
153
|
-
MemoryStore.prototype.resetAll = function () {
|
|
154
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
155
|
-
return __generator(this, function (_a) {
|
|
156
|
-
this.hits = {};
|
|
157
|
-
this.resetTime = calculateNextResetTime(this.windowMs);
|
|
158
|
-
return [2 /*return*/];
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
};
|
|
162
|
-
return MemoryStore;
|
|
163
|
-
}());
|
|
164
|
-
export default MemoryStore;
|
|
165
|
-
//# sourceMappingURL=memory-store.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"memory-store.js","sourceRoot":"","sources":["../../source/memory-store.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIhC;;;;;;;;GAQG;AACH,IAAM,sBAAsB,GAAG,UAAC,QAAgB;IAC/C,IAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAA;IAC5B,SAAS,CAAC,eAAe,CAAC,SAAS,CAAC,eAAe,EAAE,GAAG,QAAQ,CAAC,CAAA;IACjE,OAAO,SAAS,CAAA;AACjB,CAAC,CAAA;AAED;;;;;GAKG;AACH;IAAA;IA+FA,CAAC;IA7EA;;;;OAIG;IACH,0BAAI,GAAJ,UAAK,OAAgB;QAArB,iBAiBC;QAhBA,gDAAgD;QAChD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAA;QAChC,2CAA2C;QAC3C,IAAI,CAAC,SAAS,GAAG,sBAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAEtD,iCAAiC;QACjC,IAAI,CAAC,IAAI,GAAG,EAAE,CAAA;QAEd,qEAAqE;QACrE,+BAA+B;QAC/B,IAAM,QAAQ,GAAG,WAAW,CAAC;;;4BAC5B,qBAAM,IAAI,CAAC,QAAQ,EAAE,EAAA;;wBAArB,SAAqB,CAAA;;;;aACrB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QACjB,IAAI,QAAQ,CAAC,KAAK,EAAE;YACnB,QAAQ,CAAC,KAAK,EAAE,CAAA;SAChB;IACF,CAAC;IAED;;;;;;;;OAQG;IACG,+BAAS,GAAf,UAAgB,GAAW;;;;;gBACpB,SAAS,GAAG,CAAC,MAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,mCAAI,CAAC,CAAC,GAAG,CAAC,CAAA;gBAC3C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,SAAS,CAAA;gBAE1B,sBAAO;wBACN,SAAS,WAAA;wBACT,SAAS,EAAE,IAAI,CAAC,SAAS;qBACzB,EAAA;;;KACD;IAED;;;;;;OAMG;IACG,+BAAS,GAAf,UAAgB,GAAW;;;;gBACpB,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;gBAC9B,IAAI,OAAO,EAAE;oBACZ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,GAAG,CAAC,CAAA;iBAC5B;;;;KACD;IAED;;;;;;OAMG;IACG,8BAAQ,GAAd,UAAe,GAAW;;;gBACzB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;;;;KACrB;IAED;;;;OAIG;IACG,8BAAQ,GAAd;;;gBACC,IAAI,CAAC,IAAI,GAAG,EAAE,CAAA;gBACd,IAAI,CAAC,SAAS,GAAG,sBAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;;;;KACtD;IACF,kBAAC;AAAD,CAAC,AA/FD,IA+FC","sourcesContent":["// /source/memory-store.ts\n// A memory store for hit counts\n\nimport { Store, Options, IncrementResponse } from './types.js'\n\n/**\n * Calculates the time when all hit counters will be reset.\n *\n * @param windowMs {number} - The duration of a window (in milliseconds)\n *\n * @returns {Date}\n *\n * @private\n */\nconst calculateNextResetTime = (windowMs: number): Date => {\n\tconst resetTime = new Date()\n\tresetTime.setMilliseconds(resetTime.getMilliseconds() + windowMs)\n\treturn resetTime\n}\n\n/**\n * A {@link Store} that stores the hit count for each client in\n * memory.\n *\n * @public\n */\nexport default class MemoryStore implements Store {\n\t/**\n\t * The duration of time before which all hit counts are reset (in milliseconds).\n\t */\n\twindowMs!: number\n\n\t/**\n\t * The map that stores the number of hits for each client in memory.\n\t */\n\thits!: {\n\t\t[key: string]: number | undefined\n\t}\n\n\t/**\n\t * The time at which all hit counts will be reset.\n\t */\n\tresetTime!: Date\n\n\t/**\n\t * Method that initializes the store.\n\t *\n\t * @param options {Options} - The options used to setup the middleware\n\t */\n\tinit(options: Options): void {\n\t\t// Get the duration of a window from the options\n\t\tthis.windowMs = options.windowMs\n\t\t// Then calculate the reset time using that\n\t\tthis.resetTime = calculateNextResetTime(this.windowMs)\n\n\t\t// Initialise the hit counter map\n\t\tthis.hits = {}\n\n\t\t// Reset hit counts for ALL clients every `windowMs` - this will also\n\t\t// re-calculate the `resetTime`\n\t\tconst interval = setInterval(async () => {\n\t\t\tawait this.resetAll()\n\t\t}, this.windowMs)\n\t\tif (interval.unref) {\n\t\t\tinterval.unref()\n\t\t}\n\t}\n\n\t/**\n\t * Method to increment a client's hit counter.\n\t *\n\t * @param key {string} - The identifier for a client\n\t *\n\t * @returns {IncrementResponse} - The number of hits and reset time for that client\n\t *\n\t * @public\n\t */\n\tasync increment(key: string): Promise<IncrementResponse> {\n\t\tconst totalHits = (this.hits[key] ?? 0) + 1\n\t\tthis.hits[key] = totalHits\n\n\t\treturn {\n\t\t\ttotalHits,\n\t\t\tresetTime: this.resetTime,\n\t\t}\n\t}\n\n\t/**\n\t * Method to decrement a client's hit counter.\n\t *\n\t * @param key {string} - The identifier for a client\n\t *\n\t * @public\n\t */\n\tasync decrement(key: string): Promise<void> {\n\t\tconst current = this.hits[key]\n\t\tif (current) {\n\t\t\tthis.hits[key] = current - 1\n\t\t}\n\t}\n\n\t/**\n\t * Method to reset a client's hit counter.\n\t *\n\t * @param key {string} - The identifier for a client\n\t *\n\t * @public\n\t */\n\tasync resetKey(key: string): Promise<void> {\n\t\tdelete this.hits[key]\n\t}\n\n\t/**\n\t * Method to reset everyone's hit counter.\n\t *\n\t * @public\n\t */\n\tasync resetAll(): Promise<void> {\n\t\tthis.hits = {}\n\t\tthis.resetTime = calculateNextResetTime(this.windowMs)\n\t}\n}\n"]}
|
package/dist/esm/types.d.ts
DELETED
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
import Express from 'express';
|
|
2
|
-
/**
|
|
3
|
-
* Callback that fires when a client's hit counter is incremented.
|
|
4
|
-
*
|
|
5
|
-
* @param error {Error | undefined} - The error that occurred, if any
|
|
6
|
-
* @param totalHits {number} - The number of hits for that client so far
|
|
7
|
-
* @param resetTime {Date | undefined} - The time when the counter resets
|
|
8
|
-
*/
|
|
9
|
-
export declare type IncrementCallback = (error: Error | undefined, totalHits: number, resetTime: Date | undefined) => void;
|
|
10
|
-
/**
|
|
11
|
-
* Method (in the form of middleware) to generate/retrieve a value based on the
|
|
12
|
-
* incoming request
|
|
13
|
-
*
|
|
14
|
-
* @param request {Express.Request} - The Express request object
|
|
15
|
-
* @param response {Express.Response} - The Express response object
|
|
16
|
-
*
|
|
17
|
-
* @returns {T} - The value needed
|
|
18
|
-
*/
|
|
19
|
-
export declare type ValueDeterminingMiddleware<T> = (request: Express.Request, response: Express.Response) => T | Promise<T>;
|
|
20
|
-
/**
|
|
21
|
-
* Express request handler that sends back a response when a client is
|
|
22
|
-
* rate-limited.
|
|
23
|
-
*
|
|
24
|
-
* @param request {Express.Request} - The Express request object
|
|
25
|
-
* @param response {Express.Response} - The Express response object
|
|
26
|
-
* @param next {Express.NextFunction} - The Express `next` function, can be called to skip responding
|
|
27
|
-
* @param optionsUsed {Options} - The options used to set up the middleware
|
|
28
|
-
*/
|
|
29
|
-
export declare type RateLimitExceededEventHandler = (request: Express.Request, response: Express.Response, next: Express.NextFunction, optionsUsed: Options) => void;
|
|
30
|
-
/**
|
|
31
|
-
* Event callback that is triggered on a client's first request that exceeds the limit
|
|
32
|
-
* but not for subsequent requests. May be used for logging, etc. Should *not*
|
|
33
|
-
* send a response.
|
|
34
|
-
*
|
|
35
|
-
* @param request {Express.Request} - The Express request object
|
|
36
|
-
* @param response {Express.Response} - The Express response object
|
|
37
|
-
* @param optionsUsed {Options} - The options used to set up the middleware
|
|
38
|
-
*/
|
|
39
|
-
export declare type RateLimitReachedEventHandler = (request: Express.Request, response: Express.Response, optionsUsed: Options) => void;
|
|
40
|
-
/**
|
|
41
|
-
* Data returned from the `Store` when a client's hit counter is incremented.
|
|
42
|
-
*
|
|
43
|
-
* @property totalHits {number} - The number of hits for that client so far
|
|
44
|
-
* @property resetTime {Date | undefined} - The time when the counter resets
|
|
45
|
-
*/
|
|
46
|
-
export declare type IncrementResponse = {
|
|
47
|
-
totalHits: number;
|
|
48
|
-
resetTime: Date | undefined;
|
|
49
|
-
};
|
|
50
|
-
/**
|
|
51
|
-
* A modified Express request handler with the rate limit functions.
|
|
52
|
-
*/
|
|
53
|
-
export declare type RateLimitRequestHandler = Express.RequestHandler & {
|
|
54
|
-
/**
|
|
55
|
-
* Method to reset a client's hit counter.
|
|
56
|
-
*
|
|
57
|
-
* @param key {string} - The identifier for a client
|
|
58
|
-
*/
|
|
59
|
-
resetKey: (key: string) => void;
|
|
60
|
-
};
|
|
61
|
-
/**
|
|
62
|
-
* An interface that all hit counter stores must implement.
|
|
63
|
-
*
|
|
64
|
-
* @deprecated 6.x - Implement the `Store` interface instead.
|
|
65
|
-
*/
|
|
66
|
-
export interface LegacyStore {
|
|
67
|
-
/**
|
|
68
|
-
* Method to increment a client's hit counter.
|
|
69
|
-
*
|
|
70
|
-
* @param key {string} - The identifier for a client
|
|
71
|
-
* @param callback {IncrementCallback} - The callback to call once the counter is incremented
|
|
72
|
-
*/
|
|
73
|
-
incr: (key: string, callback: IncrementCallback) => void;
|
|
74
|
-
/**
|
|
75
|
-
* Method to decrement a client's hit counter.
|
|
76
|
-
*
|
|
77
|
-
* @param key {string} - The identifier for a client
|
|
78
|
-
*/
|
|
79
|
-
decrement: (key: string) => void;
|
|
80
|
-
/**
|
|
81
|
-
* Method to reset a client's hit counter.
|
|
82
|
-
*
|
|
83
|
-
* @param key {string} - The identifier for a client
|
|
84
|
-
*/
|
|
85
|
-
resetKey: (key: string) => void;
|
|
86
|
-
/**
|
|
87
|
-
* Method to reset everyone's hit counter.
|
|
88
|
-
*/
|
|
89
|
-
resetAll?: () => void;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* An interface that all hit counter stores must implement.
|
|
93
|
-
*/
|
|
94
|
-
export interface Store {
|
|
95
|
-
/**
|
|
96
|
-
* Method that initializes the store, and has access to the options passed to
|
|
97
|
-
* the middleware too.
|
|
98
|
-
*
|
|
99
|
-
* @param options {Options} - The options used to setup the middleware
|
|
100
|
-
*/
|
|
101
|
-
init?: (options: Options) => void;
|
|
102
|
-
/**
|
|
103
|
-
* Method to increment a client's hit counter.
|
|
104
|
-
*
|
|
105
|
-
* @param key {string} - The identifier for a client
|
|
106
|
-
*
|
|
107
|
-
* @returns {IncrementResponse} - The number of hits and reset time for that client
|
|
108
|
-
*/
|
|
109
|
-
increment: (key: string) => Promise<IncrementResponse> | IncrementResponse;
|
|
110
|
-
/**
|
|
111
|
-
* Method to decrement a client's hit counter.
|
|
112
|
-
*
|
|
113
|
-
* @param key {string} - The identifier for a client
|
|
114
|
-
*/
|
|
115
|
-
decrement: (key: string) => Promise<void> | void;
|
|
116
|
-
/**
|
|
117
|
-
* Method to reset a client's hit counter.
|
|
118
|
-
*
|
|
119
|
-
* @param key {string} - The identifier for a client
|
|
120
|
-
*/
|
|
121
|
-
resetKey: (key: string) => Promise<void> | void;
|
|
122
|
-
/**
|
|
123
|
-
* Method to reset everyone's hit counter.
|
|
124
|
-
*/
|
|
125
|
-
resetAll?: () => Promise<void> | void;
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* The configuration options for the rate limiter.
|
|
129
|
-
*/
|
|
130
|
-
export interface Options {
|
|
131
|
-
/**
|
|
132
|
-
* How long we should remember the requests.
|
|
133
|
-
*/
|
|
134
|
-
readonly windowMs: number;
|
|
135
|
-
/**
|
|
136
|
-
* The maximum number of connection to allow during the `window` before
|
|
137
|
-
* rate limiting the client.
|
|
138
|
-
*
|
|
139
|
-
* Can be the limit itself as a number or express middleware that parses
|
|
140
|
-
* the request and then figures out the limit.
|
|
141
|
-
*/
|
|
142
|
-
readonly max: number | ValueDeterminingMiddleware<number>;
|
|
143
|
-
/**
|
|
144
|
-
* The response body to send back when a client is rate limited.
|
|
145
|
-
*/
|
|
146
|
-
readonly message: any;
|
|
147
|
-
/**
|
|
148
|
-
* The HTTP status code to send back when a client is rate limited.
|
|
149
|
-
*
|
|
150
|
-
* Defaults to `HTTP 429 Too Many Requests` (RFC 6585).
|
|
151
|
-
*/
|
|
152
|
-
readonly statusCode: number;
|
|
153
|
-
/**
|
|
154
|
-
* Whether to send `X-RateLimit-*` headers with the rate limit and the number
|
|
155
|
-
* of requests.
|
|
156
|
-
*/
|
|
157
|
-
readonly legacyHeaders: boolean;
|
|
158
|
-
/**
|
|
159
|
-
* Whether to enable support for the rate limit standardization headers (`RateLimit-*`).
|
|
160
|
-
*/
|
|
161
|
-
readonly standardHeaders: boolean;
|
|
162
|
-
/**
|
|
163
|
-
* The name of the property on the request object to store the rate limit info.
|
|
164
|
-
*
|
|
165
|
-
* Defaults to `rateLimit`.
|
|
166
|
-
*/
|
|
167
|
-
readonly requestPropertyName: string;
|
|
168
|
-
/**
|
|
169
|
-
* If `true`, the library will (by default) skip all requests that have a 4XX
|
|
170
|
-
* or 5XX status.
|
|
171
|
-
*/
|
|
172
|
-
readonly skipFailedRequests: boolean;
|
|
173
|
-
/**
|
|
174
|
-
* If `true`, the library will (by default) skip all requests that have a
|
|
175
|
-
* status code less than 400.
|
|
176
|
-
*/
|
|
177
|
-
readonly skipSuccessfulRequests: boolean;
|
|
178
|
-
/**
|
|
179
|
-
* Method to determine whether or not the request counts as 'succesful'. Used
|
|
180
|
-
* when either `skipSuccessfulRequests` or `skipFailedRequests` is set to true.
|
|
181
|
-
*/
|
|
182
|
-
readonly requestWasSuccessful: ValueDeterminingMiddleware<boolean>;
|
|
183
|
-
/**
|
|
184
|
-
* Method to generate custom identifiers for clients.
|
|
185
|
-
*
|
|
186
|
-
* By default, the client's IP address is used.
|
|
187
|
-
*/
|
|
188
|
-
readonly keyGenerator: ValueDeterminingMiddleware<string>;
|
|
189
|
-
/**
|
|
190
|
-
* Method (in the form of middleware) to determine whether or not this request
|
|
191
|
-
* counts towards a client's quota.
|
|
192
|
-
*/
|
|
193
|
-
readonly skip: ValueDeterminingMiddleware<boolean>;
|
|
194
|
-
/**
|
|
195
|
-
* Express request handler that sends back a response when a client is
|
|
196
|
-
* rate-limited.
|
|
197
|
-
*/
|
|
198
|
-
readonly handler: RateLimitExceededEventHandler;
|
|
199
|
-
/**
|
|
200
|
-
* Express request handler that sends back a response when a client has
|
|
201
|
-
* reached their rate limit, and will be rate limited on their next request.
|
|
202
|
-
*/
|
|
203
|
-
readonly onLimitReached: RateLimitReachedEventHandler;
|
|
204
|
-
/**
|
|
205
|
-
* The {@link Store} to use to store the hit count for each client.
|
|
206
|
-
*/
|
|
207
|
-
store: Store;
|
|
208
|
-
/**
|
|
209
|
-
* Whether to send `X-RateLimit-*` headers with the rate limit and the number
|
|
210
|
-
* of requests.
|
|
211
|
-
*
|
|
212
|
-
* @deprecated 6.x - This option was renamed to `legacyHeaders`.
|
|
213
|
-
*/
|
|
214
|
-
headers?: boolean;
|
|
215
|
-
/**
|
|
216
|
-
* Whether to send `RateLimit-*` headers with the rate limit and the number
|
|
217
|
-
* of requests.
|
|
218
|
-
*
|
|
219
|
-
* @deprecated 6.x - This option was renamed to `standardHeaders`.
|
|
220
|
-
*/
|
|
221
|
-
draft_polli_ratelimit_headers?: boolean;
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* The extended request object that includes information about the client's
|
|
225
|
-
* rate limit.
|
|
226
|
-
*/
|
|
227
|
-
export declare type AugmentedRequest = Express.Request & {
|
|
228
|
-
[key: string]: RateLimitInfo;
|
|
229
|
-
};
|
|
230
|
-
/**
|
|
231
|
-
* The rate limit related information for each client included in the
|
|
232
|
-
* Express request object.
|
|
233
|
-
*/
|
|
234
|
-
export interface RateLimitInfo {
|
|
235
|
-
readonly limit: number;
|
|
236
|
-
readonly current: number;
|
|
237
|
-
readonly remaining: number;
|
|
238
|
-
readonly resetTime: Date | undefined;
|
|
239
|
-
}
|
package/dist/esm/types.js
DELETED
package/dist/esm/types.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../source/types.ts"],"names":[],"mappings":"AAAA,mBAAmB;AACnB,qCAAqC","sourcesContent":["// /source/types.ts\n// All the types used by this package\n\nimport Express from 'express'\n\n/**\n * Callback that fires when a client's hit counter is incremented.\n *\n * @param error {Error | undefined} - The error that occurred, if any\n * @param totalHits {number} - The number of hits for that client so far\n * @param resetTime {Date | undefined} - The time when the counter resets\n */\nexport type IncrementCallback = (\n\terror: Error | undefined,\n\ttotalHits: number,\n\tresetTime: Date | undefined,\n) => void\n\n/**\n * Method (in the form of middleware) to generate/retrieve a value based on the\n * incoming request\n *\n * @param request {Express.Request} - The Express request object\n * @param response {Express.Response} - The Express response object\n *\n * @returns {T} - The value needed\n */\nexport type ValueDeterminingMiddleware<T> = (\n\trequest: Express.Request,\n\tresponse: Express.Response,\n) => T | Promise<T>\n\n/**\n * Express request handler that sends back a response when a client is\n * rate-limited.\n *\n * @param request {Express.Request} - The Express request object\n * @param response {Express.Response} - The Express response object\n * @param next {Express.NextFunction} - The Express `next` function, can be called to skip responding\n * @param optionsUsed {Options} - The options used to set up the middleware\n */\nexport type RateLimitExceededEventHandler = (\n\trequest: Express.Request,\n\tresponse: Express.Response,\n\tnext: Express.NextFunction,\n\toptionsUsed: Options,\n) => void\n\n/**\n * Event callback that is triggered on a client's first request that exceeds the limit\n * but not for subsequent requests. May be used for logging, etc. Should *not*\n * send a response.\n *\n * @param request {Express.Request} - The Express request object\n * @param response {Express.Response} - The Express response object\n * @param optionsUsed {Options} - The options used to set up the middleware\n */\nexport type RateLimitReachedEventHandler = (\n\trequest: Express.Request,\n\tresponse: Express.Response,\n\toptionsUsed: Options,\n) => void\n\n/**\n * Data returned from the `Store` when a client's hit counter is incremented.\n *\n * @property totalHits {number} - The number of hits for that client so far\n * @property resetTime {Date | undefined} - The time when the counter resets\n */\nexport type IncrementResponse = {\n\ttotalHits: number\n\tresetTime: Date | undefined\n}\n\n/**\n * A modified Express request handler with the rate limit functions.\n */\nexport type RateLimitRequestHandler = Express.RequestHandler & {\n\t/**\n\t * Method to reset a client's hit counter.\n\t *\n\t * @param key {string} - The identifier for a client\n\t */\n\tresetKey: (key: string) => void\n}\n\n/**\n * An interface that all hit counter stores must implement.\n *\n * @deprecated 6.x - Implement the `Store` interface instead.\n */\nexport interface LegacyStore {\n\t/**\n\t * Method to increment a client's hit counter.\n\t *\n\t * @param key {string} - The identifier for a client\n\t * @param callback {IncrementCallback} - The callback to call once the counter is incremented\n\t */\n\tincr: (key: string, callback: IncrementCallback) => void\n\n\t/**\n\t * Method to decrement a client's hit counter.\n\t *\n\t * @param key {string} - The identifier for a client\n\t */\n\tdecrement: (key: string) => void\n\n\t/**\n\t * Method to reset a client's hit counter.\n\t *\n\t * @param key {string} - The identifier for a client\n\t */\n\tresetKey: (key: string) => void\n\n\t/**\n\t * Method to reset everyone's hit counter.\n\t */\n\tresetAll?: () => void\n}\n\n/**\n * An interface that all hit counter stores must implement.\n */\nexport interface Store {\n\t/**\n\t * Method that initializes the store, and has access to the options passed to\n\t * the middleware too.\n\t *\n\t * @param options {Options} - The options used to setup the middleware\n\t */\n\tinit?: (options: Options) => void\n\n\t/**\n\t * Method to increment a client's hit counter.\n\t *\n\t * @param key {string} - The identifier for a client\n\t *\n\t * @returns {IncrementResponse} - The number of hits and reset time for that client\n\t */\n\tincrement: (key: string) => Promise<IncrementResponse> | IncrementResponse\n\n\t/**\n\t * Method to decrement a client's hit counter.\n\t *\n\t * @param key {string} - The identifier for a client\n\t */\n\tdecrement: (key: string) => Promise<void> | void\n\n\t/**\n\t * Method to reset a client's hit counter.\n\t *\n\t * @param key {string} - The identifier for a client\n\t */\n\tresetKey: (key: string) => Promise<void> | void\n\n\t/**\n\t * Method to reset everyone's hit counter.\n\t */\n\tresetAll?: () => Promise<void> | void\n}\n\n/**\n * The configuration options for the rate limiter.\n */\nexport interface Options {\n\t/**\n\t * How long we should remember the requests.\n\t */\n\treadonly windowMs: number\n\n\t/**\n\t * The maximum number of connection to allow during the `window` before\n\t * rate limiting the client.\n\t *\n\t * Can be the limit itself as a number or express middleware that parses\n\t * the request and then figures out the limit.\n\t */\n\treadonly max: number | ValueDeterminingMiddleware<number>\n\n\t/**\n\t * The response body to send back when a client is rate limited.\n\t */\n\treadonly message: any\n\n\t/**\n\t * The HTTP status code to send back when a client is rate limited.\n\t *\n\t * Defaults to `HTTP 429 Too Many Requests` (RFC 6585).\n\t */\n\treadonly statusCode: number\n\n\t/**\n\t * Whether to send `X-RateLimit-*` headers with the rate limit and the number\n\t * of requests.\n\t */\n\treadonly legacyHeaders: boolean\n\n\t/**\n\t * Whether to enable support for the rate limit standardization headers (`RateLimit-*`).\n\t */\n\treadonly standardHeaders: boolean\n\n\t/**\n\t * The name of the property on the request object to store the rate limit info.\n\t *\n\t * Defaults to `rateLimit`.\n\t */\n\treadonly requestPropertyName: string\n\n\t/**\n\t * If `true`, the library will (by default) skip all requests that have a 4XX\n\t * or 5XX status.\n\t */\n\treadonly skipFailedRequests: boolean\n\n\t/**\n\t * If `true`, the library will (by default) skip all requests that have a\n\t * status code less than 400.\n\t */\n\treadonly skipSuccessfulRequests: boolean\n\n\t/**\n\t * Method to determine whether or not the request counts as 'succesful'. Used\n\t * when either `skipSuccessfulRequests` or `skipFailedRequests` is set to true.\n\t */\n\treadonly requestWasSuccessful: ValueDeterminingMiddleware<boolean>\n\n\t/**\n\t * Method to generate custom identifiers for clients.\n\t *\n\t * By default, the client's IP address is used.\n\t */\n\treadonly keyGenerator: ValueDeterminingMiddleware<string>\n\n\t/**\n\t * Method (in the form of middleware) to determine whether or not this request\n\t * counts towards a client's quota.\n\t */\n\treadonly skip: ValueDeterminingMiddleware<boolean>\n\n\t/**\n\t * Express request handler that sends back a response when a client is\n\t * rate-limited.\n\t */\n\treadonly handler: RateLimitExceededEventHandler\n\n\t/**\n\t * Express request handler that sends back a response when a client has\n\t * reached their rate limit, and will be rate limited on their next request.\n\t */\n\treadonly onLimitReached: RateLimitReachedEventHandler\n\n\t/**\n\t * The {@link Store} to use to store the hit count for each client.\n\t */\n\tstore: Store\n\n\t/**\n\t * Whether to send `X-RateLimit-*` headers with the rate limit and the number\n\t * of requests.\n\t *\n\t * @deprecated 6.x - This option was renamed to `legacyHeaders`.\n\t */\n\theaders?: boolean\n\n\t/**\n\t * Whether to send `RateLimit-*` headers with the rate limit and the number\n\t * of requests.\n\t *\n\t * @deprecated 6.x - This option was renamed to `standardHeaders`.\n\t */\n\tdraft_polli_ratelimit_headers?: boolean\n}\n\n/**\n * The extended request object that includes information about the client's\n * rate limit.\n */\nexport type AugmentedRequest = Express.Request & {\n\t[key: string]: RateLimitInfo\n}\n\n/**\n * The rate limit related information for each client included in the\n * Express request object.\n */\nexport interface RateLimitInfo {\n\treadonly limit: number\n\treadonly current: number\n\treadonly remaining: number\n\treadonly resetTime: Date | undefined\n}\n"]}
|