@depup/express-slow-down 3.1.0-depup.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/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # @depup/express-slow-down
2
+
3
+ > Dependency-bumped version of [express-slow-down](https://www.npmjs.com/package/express-slow-down)
4
+
5
+ Generated by [DepUp](https://github.com/depup/npm) -- all production
6
+ dependencies bumped to latest versions.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install @depup/express-slow-down
12
+ ```
13
+
14
+ | Field | Value |
15
+ |-------|-------|
16
+ | Original | [express-slow-down](https://www.npmjs.com/package/express-slow-down) @ 3.1.0 |
17
+ | Processed | 2026-03-19 |
18
+ | Smoke test | passed |
19
+ | Deps updated | 1 |
20
+
21
+ ## Dependency Changes
22
+
23
+ | Dependency | From | To |
24
+ |------------|------|-----|
25
+ | express-rate-limit | 8 | ^8.3.1 |
26
+
27
+ ---
28
+
29
+ Source: https://github.com/depup/npm | Original: https://www.npmjs.com/package/express-slow-down
30
+
31
+ License inherited from the original package.
package/changelog.md ADDED
@@ -0,0 +1,84 @@
1
+ # express-slow-down changelog
2
+
3
+ ## v3.1.0
4
+
5
+ ### Added
6
+
7
+ - `legacyHeaders` and `standardHeaders` options can now be passed through to
8
+ express-rate-limit
9
+
10
+ ## v3.0.1
11
+
12
+ ### Fixed
13
+
14
+ - Only pass supported options to express-rate-limit to avoid triggering warning
15
+ added for unexpected options in ERL v8.2.0
16
+
17
+ ## v3.0.0
18
+
19
+ ### Added
20
+
21
+ - Added support for grouping IPv6 addresses by subnet (defaults to /56) via
22
+ upgrading express-rate-limit dependency to 8.x
23
+
24
+ ## v2.1.0
25
+
26
+ ### Fixed
27
+
28
+ - Changed distributed JS to no longer bundle in `express-rate-limit`, instead
29
+ using the version installed via npm. This enables several new
30
+ express-rate-limit features that have been released since v7.0.1.
31
+
32
+ ## v2.0.3
33
+
34
+ ### Fixed
35
+
36
+ - Fixed `peerDependencies` compatibility with express 5 beta.
37
+
38
+ ## v2.0.2
39
+
40
+ ### Fixed
41
+
42
+ - Allowed `express-slow-down` to be used with `express` v5.
43
+
44
+ ## v2.0.1
45
+
46
+ ### Fixed
47
+
48
+ - Fixed an incorrect `WRN_ERL_MAX_ZERO` warning when supplying a custom
49
+ validation object in the config.
50
+
51
+ ## v2.0.0
52
+
53
+ express-slow-down v2 is built on top of express-rate-limit v7.
54
+
55
+ ### Breaking
56
+
57
+ - Changed behavior of `delayMs` when set to a number
58
+ - Previous behavior multiplied `delayMs` value by the number of slowed
59
+ requests to determine the delay amount
60
+ - New behavior treats a numeric value as a fixed delay that is applied to each
61
+ slowed request without multiplication
62
+ - Set to `function(used) { return (used - this.delayAfter) * 1000; }` to
63
+ restore old behavior. (Change `1000` to match old value if necessary.)
64
+ - Changed arguments passed to `delayMs` when set to a function
65
+ - Previous signature was `function(req, res): number`
66
+ - New signature is `function(used, req, res): number | Promise<number>` where
67
+ `used` is the number of hits from this user during the current window
68
+ - Dropped support for `onLimitReached` method
69
+ - Dropped support for `headers` option
70
+ - Renamed `req.slowDown.current` to `req.slowDown.used`
71
+ - `current` is now a hidden getter that will return the `used` value, but will
72
+ not be included when iteration over keys or running through
73
+ `JSON.stringify()`
74
+
75
+ ### Added
76
+
77
+ - `delayAfter`, `delayMs`, and `maxDelayMs` may now be async functions that
78
+ return a number or a promise that resolves to a number
79
+ - The MemoryStore now uses precise, per-user reset times rather than a global
80
+ window that resets all users at once.
81
+ - Now using express-rate-limit's validator to detect and warn about common
82
+ misconfigurations. See
83
+ https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes for
84
+ more info.
package/changes.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "bumped": {
3
+ "express-rate-limit": {
4
+ "from": "8",
5
+ "to": "^8.3.1"
6
+ }
7
+ },
8
+ "timestamp": "2026-03-19T03:03:47.222Z",
9
+ "totalUpdated": 1
10
+ }
package/dist/index.cjs ADDED
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // source/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ default: () => slow_down_default,
24
+ slowDown: () => slowDown
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // source/slow-down.ts
29
+ var import_express_rate_limit = require("express-rate-limit");
30
+ var filterUndefinedOptions = (passedOptions) => {
31
+ const filteredOptions = {};
32
+ for (const k of Object.keys(passedOptions)) {
33
+ const key = k;
34
+ if (passedOptions[key] !== void 0) {
35
+ filteredOptions[key] = passedOptions[key];
36
+ }
37
+ }
38
+ return filteredOptions;
39
+ };
40
+ var ExpressSlowDownWarning = class extends Error {
41
+ constructor(code, message) {
42
+ const url = `https://express-rate-limit.github.io/${code}/`;
43
+ super(`${message} See ${url} for more information.`);
44
+ this.name = this.constructor.name;
45
+ this.code = code;
46
+ this.help = url;
47
+ }
48
+ };
49
+ var slowDown = (passedOptions = {}) => {
50
+ const notUndefinedOptions = filterUndefinedOptions(passedOptions);
51
+ if (notUndefinedOptions.max !== void 0 || notUndefinedOptions.limit !== void 0)
52
+ throw new Error(
53
+ "The limit/max option is not supported by express-slow-down, please use delayAfter instead."
54
+ );
55
+ const validate = typeof notUndefinedOptions.validate === "boolean" ? { default: notUndefinedOptions.validate } : notUndefinedOptions.validate ?? { default: true };
56
+ if (typeof notUndefinedOptions.delayMs === "number" && // Make sure the validation check is not disabled.
57
+ (validate.delayMs === true || validate.delayMs === void 0 && validate.default)) {
58
+ const message = `The behaviour of the 'delayMs' option was changed in express-slow-down v2:
59
+ - For the old behavior, change the delayMs option to:
60
+
61
+ delayMs: (used, req) => {
62
+ const delayAfter = req.${notUndefinedOptions.requestPropertyName ?? "slowDown"}.limit;
63
+ return (used - delayAfter) * ${notUndefinedOptions.delayMs};
64
+ },
65
+
66
+ - For the new behavior, change the delayMs option to:
67
+
68
+ delayMs: () => ${notUndefinedOptions.delayMs},
69
+
70
+ Or set 'options.validate: {delayMs: false}' to disable this message.`.replace(
71
+ /^(\t){3}/gm,
72
+ ""
73
+ );
74
+ console.warn(new ExpressSlowDownWarning("WRN_ESD_DELAYMS", message));
75
+ }
76
+ delete validate?.delayMs;
77
+ const options = {
78
+ // The following settings are defaults that may be overridden by the user's options.
79
+ delayAfter: 1,
80
+ delayMs(used, request, response) {
81
+ const delayAfter2 = request[options.requestPropertyName].limit;
82
+ return (used - delayAfter2) * 1e3;
83
+ },
84
+ maxDelayMs: Number.POSITIVE_INFINITY,
85
+ requestPropertyName: "slowDown",
86
+ // Disable the headers by default, but allow users to override
87
+ legacyHeaders: false,
88
+ standardHeaders: false,
89
+ // Next the user's options are pulled in, overriding defaults from above
90
+ ...notUndefinedOptions,
91
+ // This is a combination of the user's validate settings and our own overrides
92
+ validate: {
93
+ ...validate,
94
+ limit: false
95
+ // We know the behavior of limit=0 changed - we depend on the new behavior!
96
+ },
97
+ // These settings cannot be overridden.
98
+ limit: 0,
99
+ // We want the handler to run on every request.
100
+ // The handler contains the slow-down logic, so don't allow it to be overridden.
101
+ async handler(_request, response, next) {
102
+ const delayAfter2 = typeof options.delayAfter === "function" ? await options.delayAfter(_request, response) : options.delayAfter;
103
+ const request = _request;
104
+ const info = request[options.requestPropertyName];
105
+ info.limit = delayAfter2;
106
+ info.remaining = Math.max(0, delayAfter2 - info.used);
107
+ let delay = 0;
108
+ if (info.used > delayAfter2) {
109
+ const unboundedDelay = typeof options.delayMs === "function" ? await options.delayMs(info.used, request, response) : options.delayMs;
110
+ const maxDelayMs2 = typeof options.maxDelayMs === "function" ? await options.maxDelayMs(request, response) : options.maxDelayMs;
111
+ delay = Math.max(0, Math.min(unboundedDelay, maxDelayMs2));
112
+ }
113
+ request[options.requestPropertyName].delay = delay;
114
+ if (delay <= 0) return next();
115
+ const timerId = setTimeout(() => next(), delay);
116
+ response.on("close", () => clearTimeout(timerId));
117
+ }
118
+ };
119
+ const { delayAfter, delayMs, maxDelayMs, ...erlOptions } = options;
120
+ return (0, import_express_rate_limit.rateLimit)(erlOptions);
121
+ };
122
+ var slow_down_default = slowDown;
123
+ // Annotate the CommonJS export names for ESM import in node:
124
+ 0 && (module.exports = {
125
+ slowDown
126
+ });
127
+ module.exports = slowDown; module.exports.default = slowDown; module.exports.slowDown = slowDown;
@@ -0,0 +1,112 @@
1
+ // Generated by dts-bundle-generator v8.0.1
2
+
3
+ import { Response } from 'express';
4
+ import { AugmentedRequest as RateLimitedRequest, EnabledValidations, Options as RateLimitOptions, RateLimitInfo, RateLimitRequestHandler, ValueDeterminingMiddleware } from 'express-rate-limit';
5
+
6
+ /**
7
+ * A modified Express request handler with the rate limit and slow down methods.
8
+ */
9
+ export type SlowDownRequestHandler = RateLimitRequestHandler;
10
+ /**
11
+ * Method to generate the delay to apply to the incoming request.
12
+ *
13
+ * @param used {number} - The number of requests made by the client so far.
14
+ * @param request {Request} - The Express request object.
15
+ * @param response {Response} - The Express response object.
16
+ *
17
+ * @returns {number} - The delay to apply.
18
+ */
19
+ export type DelayFn = (used: number, request: AugmentedRequest, response: Response) => number | Promise<number>;
20
+ /**
21
+ * Extra validation checks provided by `express-slow-down`.
22
+ */
23
+ export type ExtendedValidations = EnabledValidations & {
24
+ delayMs?: boolean;
25
+ };
26
+ /**
27
+ * Options present in `express-rate-limit` that this package overrides.
28
+ */
29
+ export type OverriddenOptions = {
30
+ /**
31
+ * The `limit` option is set from the handler using `delayAfter`.
32
+ */
33
+ limit: never;
34
+ max: never;
35
+ /**
36
+ * The `handler` option is overridden by the library.
37
+ */
38
+ handler: never;
39
+ };
40
+ export type OverridenOptions = OverriddenOptions;
41
+ /**
42
+ * All the `express-slow-down` specific options.
43
+ */
44
+ export type SlowDownOptions = {
45
+ /**
46
+ * The max number of requests allowed during windowMs before the middleware
47
+ * starts delaying responses.
48
+ *
49
+ * Can be the limit itself as a number or a (sync/async) function that accepts
50
+ * the Express req and res objects and then returns a number.
51
+ *
52
+ * Defaults to 1.
53
+ */
54
+ delayAfter: number | ValueDeterminingMiddleware<number>;
55
+ /**
56
+ * The delay to apply to each request once the limit is reached.
57
+ *
58
+ * Can be the limit itself as a number or a (sync/async) function that accepts
59
+ * the Express req and res objects and then returns a number.
60
+ *
61
+ * By default, it increases the delay by 1 second for every request over the limit.
62
+ */
63
+ delayMs: number | DelayFn;
64
+ /**
65
+ * The absolute maximum value for delayMs. After many consecutive attempts,
66
+ * the delay will always be this value. This option should be used especially
67
+ * when your application is running behind a load balancer or reverse proxy
68
+ * that has a request timeout.
69
+ *
70
+ * Defaults to infinity.
71
+ */
72
+ maxDelayMs: number | ValueDeterminingMiddleware<number>;
73
+ /**
74
+ * Allows the developer to turn off the validation check for `delayMs` being a
75
+ * function.
76
+ */
77
+ validate: boolean | ExtendedValidations;
78
+ };
79
+ /**
80
+ * The configuration options for the middleware.
81
+ */
82
+ export type Options = RateLimitOptions & OverriddenOptions & SlowDownOptions;
83
+ /**
84
+ * The extended request object that includes information about the client's
85
+ * rate limit and delay.
86
+ */
87
+ export type AugmentedRequest = RateLimitedRequest & {
88
+ [key: string]: SlowDownInfo;
89
+ };
90
+ /**
91
+ * The rate limit and delay related information for each client included in the
92
+ * Express request object.
93
+ */
94
+ export type SlowDownInfo = RateLimitInfo & {
95
+ delay: number;
96
+ };
97
+ /**
98
+ * Create an instance of middleware that slows down responses to Express requests.
99
+ *
100
+ * @param passedOptions {Options} - Options to configure the speed limiter.
101
+ *
102
+ * @returns {SlowDownRequestHandle} - The middleware that speed-limits clients based on your configuration.
103
+ *
104
+ * @public
105
+ */
106
+ export declare const slowDown: (passedOptions?: Partial<Options>) => SlowDownRequestHandler;
107
+
108
+ export {
109
+ slowDown as default,
110
+ };
111
+
112
+ export {};
@@ -0,0 +1,112 @@
1
+ // Generated by dts-bundle-generator v8.0.1
2
+
3
+ import { Response } from 'express';
4
+ import { AugmentedRequest as RateLimitedRequest, EnabledValidations, Options as RateLimitOptions, RateLimitInfo, RateLimitRequestHandler, ValueDeterminingMiddleware } from 'express-rate-limit';
5
+
6
+ /**
7
+ * A modified Express request handler with the rate limit and slow down methods.
8
+ */
9
+ export type SlowDownRequestHandler = RateLimitRequestHandler;
10
+ /**
11
+ * Method to generate the delay to apply to the incoming request.
12
+ *
13
+ * @param used {number} - The number of requests made by the client so far.
14
+ * @param request {Request} - The Express request object.
15
+ * @param response {Response} - The Express response object.
16
+ *
17
+ * @returns {number} - The delay to apply.
18
+ */
19
+ export type DelayFn = (used: number, request: AugmentedRequest, response: Response) => number | Promise<number>;
20
+ /**
21
+ * Extra validation checks provided by `express-slow-down`.
22
+ */
23
+ export type ExtendedValidations = EnabledValidations & {
24
+ delayMs?: boolean;
25
+ };
26
+ /**
27
+ * Options present in `express-rate-limit` that this package overrides.
28
+ */
29
+ export type OverriddenOptions = {
30
+ /**
31
+ * The `limit` option is set from the handler using `delayAfter`.
32
+ */
33
+ limit: never;
34
+ max: never;
35
+ /**
36
+ * The `handler` option is overridden by the library.
37
+ */
38
+ handler: never;
39
+ };
40
+ export type OverridenOptions = OverriddenOptions;
41
+ /**
42
+ * All the `express-slow-down` specific options.
43
+ */
44
+ export type SlowDownOptions = {
45
+ /**
46
+ * The max number of requests allowed during windowMs before the middleware
47
+ * starts delaying responses.
48
+ *
49
+ * Can be the limit itself as a number or a (sync/async) function that accepts
50
+ * the Express req and res objects and then returns a number.
51
+ *
52
+ * Defaults to 1.
53
+ */
54
+ delayAfter: number | ValueDeterminingMiddleware<number>;
55
+ /**
56
+ * The delay to apply to each request once the limit is reached.
57
+ *
58
+ * Can be the limit itself as a number or a (sync/async) function that accepts
59
+ * the Express req and res objects and then returns a number.
60
+ *
61
+ * By default, it increases the delay by 1 second for every request over the limit.
62
+ */
63
+ delayMs: number | DelayFn;
64
+ /**
65
+ * The absolute maximum value for delayMs. After many consecutive attempts,
66
+ * the delay will always be this value. This option should be used especially
67
+ * when your application is running behind a load balancer or reverse proxy
68
+ * that has a request timeout.
69
+ *
70
+ * Defaults to infinity.
71
+ */
72
+ maxDelayMs: number | ValueDeterminingMiddleware<number>;
73
+ /**
74
+ * Allows the developer to turn off the validation check for `delayMs` being a
75
+ * function.
76
+ */
77
+ validate: boolean | ExtendedValidations;
78
+ };
79
+ /**
80
+ * The configuration options for the middleware.
81
+ */
82
+ export type Options = RateLimitOptions & OverriddenOptions & SlowDownOptions;
83
+ /**
84
+ * The extended request object that includes information about the client's
85
+ * rate limit and delay.
86
+ */
87
+ export type AugmentedRequest = RateLimitedRequest & {
88
+ [key: string]: SlowDownInfo;
89
+ };
90
+ /**
91
+ * The rate limit and delay related information for each client included in the
92
+ * Express request object.
93
+ */
94
+ export type SlowDownInfo = RateLimitInfo & {
95
+ delay: number;
96
+ };
97
+ /**
98
+ * Create an instance of middleware that slows down responses to Express requests.
99
+ *
100
+ * @param passedOptions {Options} - Options to configure the speed limiter.
101
+ *
102
+ * @returns {SlowDownRequestHandle} - The middleware that speed-limits clients based on your configuration.
103
+ *
104
+ * @public
105
+ */
106
+ export declare const slowDown: (passedOptions?: Partial<Options>) => SlowDownRequestHandler;
107
+
108
+ export {
109
+ slowDown as default,
110
+ };
111
+
112
+ export {};
@@ -0,0 +1,112 @@
1
+ // Generated by dts-bundle-generator v8.0.1
2
+
3
+ import { Response } from 'express';
4
+ import { AugmentedRequest as RateLimitedRequest, EnabledValidations, Options as RateLimitOptions, RateLimitInfo, RateLimitRequestHandler, ValueDeterminingMiddleware } from 'express-rate-limit';
5
+
6
+ /**
7
+ * A modified Express request handler with the rate limit and slow down methods.
8
+ */
9
+ export type SlowDownRequestHandler = RateLimitRequestHandler;
10
+ /**
11
+ * Method to generate the delay to apply to the incoming request.
12
+ *
13
+ * @param used {number} - The number of requests made by the client so far.
14
+ * @param request {Request} - The Express request object.
15
+ * @param response {Response} - The Express response object.
16
+ *
17
+ * @returns {number} - The delay to apply.
18
+ */
19
+ export type DelayFn = (used: number, request: AugmentedRequest, response: Response) => number | Promise<number>;
20
+ /**
21
+ * Extra validation checks provided by `express-slow-down`.
22
+ */
23
+ export type ExtendedValidations = EnabledValidations & {
24
+ delayMs?: boolean;
25
+ };
26
+ /**
27
+ * Options present in `express-rate-limit` that this package overrides.
28
+ */
29
+ export type OverriddenOptions = {
30
+ /**
31
+ * The `limit` option is set from the handler using `delayAfter`.
32
+ */
33
+ limit: never;
34
+ max: never;
35
+ /**
36
+ * The `handler` option is overridden by the library.
37
+ */
38
+ handler: never;
39
+ };
40
+ export type OverridenOptions = OverriddenOptions;
41
+ /**
42
+ * All the `express-slow-down` specific options.
43
+ */
44
+ export type SlowDownOptions = {
45
+ /**
46
+ * The max number of requests allowed during windowMs before the middleware
47
+ * starts delaying responses.
48
+ *
49
+ * Can be the limit itself as a number or a (sync/async) function that accepts
50
+ * the Express req and res objects and then returns a number.
51
+ *
52
+ * Defaults to 1.
53
+ */
54
+ delayAfter: number | ValueDeterminingMiddleware<number>;
55
+ /**
56
+ * The delay to apply to each request once the limit is reached.
57
+ *
58
+ * Can be the limit itself as a number or a (sync/async) function that accepts
59
+ * the Express req and res objects and then returns a number.
60
+ *
61
+ * By default, it increases the delay by 1 second for every request over the limit.
62
+ */
63
+ delayMs: number | DelayFn;
64
+ /**
65
+ * The absolute maximum value for delayMs. After many consecutive attempts,
66
+ * the delay will always be this value. This option should be used especially
67
+ * when your application is running behind a load balancer or reverse proxy
68
+ * that has a request timeout.
69
+ *
70
+ * Defaults to infinity.
71
+ */
72
+ maxDelayMs: number | ValueDeterminingMiddleware<number>;
73
+ /**
74
+ * Allows the developer to turn off the validation check for `delayMs` being a
75
+ * function.
76
+ */
77
+ validate: boolean | ExtendedValidations;
78
+ };
79
+ /**
80
+ * The configuration options for the middleware.
81
+ */
82
+ export type Options = RateLimitOptions & OverriddenOptions & SlowDownOptions;
83
+ /**
84
+ * The extended request object that includes information about the client's
85
+ * rate limit and delay.
86
+ */
87
+ export type AugmentedRequest = RateLimitedRequest & {
88
+ [key: string]: SlowDownInfo;
89
+ };
90
+ /**
91
+ * The rate limit and delay related information for each client included in the
92
+ * Express request object.
93
+ */
94
+ export type SlowDownInfo = RateLimitInfo & {
95
+ delay: number;
96
+ };
97
+ /**
98
+ * Create an instance of middleware that slows down responses to Express requests.
99
+ *
100
+ * @param passedOptions {Options} - Options to configure the speed limiter.
101
+ *
102
+ * @returns {SlowDownRequestHandle} - The middleware that speed-limits clients based on your configuration.
103
+ *
104
+ * @public
105
+ */
106
+ export declare const slowDown: (passedOptions?: Partial<Options>) => SlowDownRequestHandler;
107
+
108
+ export {
109
+ slowDown as default,
110
+ };
111
+
112
+ export {};
package/dist/index.mjs ADDED
@@ -0,0 +1,99 @@
1
+ // source/slow-down.ts
2
+ import { rateLimit } from "express-rate-limit";
3
+ var filterUndefinedOptions = (passedOptions) => {
4
+ const filteredOptions = {};
5
+ for (const k of Object.keys(passedOptions)) {
6
+ const key = k;
7
+ if (passedOptions[key] !== void 0) {
8
+ filteredOptions[key] = passedOptions[key];
9
+ }
10
+ }
11
+ return filteredOptions;
12
+ };
13
+ var ExpressSlowDownWarning = class extends Error {
14
+ constructor(code, message) {
15
+ const url = `https://express-rate-limit.github.io/${code}/`;
16
+ super(`${message} See ${url} for more information.`);
17
+ this.name = this.constructor.name;
18
+ this.code = code;
19
+ this.help = url;
20
+ }
21
+ };
22
+ var slowDown = (passedOptions = {}) => {
23
+ const notUndefinedOptions = filterUndefinedOptions(passedOptions);
24
+ if (notUndefinedOptions.max !== void 0 || notUndefinedOptions.limit !== void 0)
25
+ throw new Error(
26
+ "The limit/max option is not supported by express-slow-down, please use delayAfter instead."
27
+ );
28
+ const validate = typeof notUndefinedOptions.validate === "boolean" ? { default: notUndefinedOptions.validate } : notUndefinedOptions.validate ?? { default: true };
29
+ if (typeof notUndefinedOptions.delayMs === "number" && // Make sure the validation check is not disabled.
30
+ (validate.delayMs === true || validate.delayMs === void 0 && validate.default)) {
31
+ const message = `The behaviour of the 'delayMs' option was changed in express-slow-down v2:
32
+ - For the old behavior, change the delayMs option to:
33
+
34
+ delayMs: (used, req) => {
35
+ const delayAfter = req.${notUndefinedOptions.requestPropertyName ?? "slowDown"}.limit;
36
+ return (used - delayAfter) * ${notUndefinedOptions.delayMs};
37
+ },
38
+
39
+ - For the new behavior, change the delayMs option to:
40
+
41
+ delayMs: () => ${notUndefinedOptions.delayMs},
42
+
43
+ Or set 'options.validate: {delayMs: false}' to disable this message.`.replace(
44
+ /^(\t){3}/gm,
45
+ ""
46
+ );
47
+ console.warn(new ExpressSlowDownWarning("WRN_ESD_DELAYMS", message));
48
+ }
49
+ delete validate?.delayMs;
50
+ const options = {
51
+ // The following settings are defaults that may be overridden by the user's options.
52
+ delayAfter: 1,
53
+ delayMs(used, request, response) {
54
+ const delayAfter2 = request[options.requestPropertyName].limit;
55
+ return (used - delayAfter2) * 1e3;
56
+ },
57
+ maxDelayMs: Number.POSITIVE_INFINITY,
58
+ requestPropertyName: "slowDown",
59
+ // Disable the headers by default, but allow users to override
60
+ legacyHeaders: false,
61
+ standardHeaders: false,
62
+ // Next the user's options are pulled in, overriding defaults from above
63
+ ...notUndefinedOptions,
64
+ // This is a combination of the user's validate settings and our own overrides
65
+ validate: {
66
+ ...validate,
67
+ limit: false
68
+ // We know the behavior of limit=0 changed - we depend on the new behavior!
69
+ },
70
+ // These settings cannot be overridden.
71
+ limit: 0,
72
+ // We want the handler to run on every request.
73
+ // The handler contains the slow-down logic, so don't allow it to be overridden.
74
+ async handler(_request, response, next) {
75
+ const delayAfter2 = typeof options.delayAfter === "function" ? await options.delayAfter(_request, response) : options.delayAfter;
76
+ const request = _request;
77
+ const info = request[options.requestPropertyName];
78
+ info.limit = delayAfter2;
79
+ info.remaining = Math.max(0, delayAfter2 - info.used);
80
+ let delay = 0;
81
+ if (info.used > delayAfter2) {
82
+ const unboundedDelay = typeof options.delayMs === "function" ? await options.delayMs(info.used, request, response) : options.delayMs;
83
+ const maxDelayMs2 = typeof options.maxDelayMs === "function" ? await options.maxDelayMs(request, response) : options.maxDelayMs;
84
+ delay = Math.max(0, Math.min(unboundedDelay, maxDelayMs2));
85
+ }
86
+ request[options.requestPropertyName].delay = delay;
87
+ if (delay <= 0) return next();
88
+ const timerId = setTimeout(() => next(), delay);
89
+ response.on("close", () => clearTimeout(timerId));
90
+ }
91
+ };
92
+ const { delayAfter, delayMs, maxDelayMs, ...erlOptions } = options;
93
+ return rateLimit(erlOptions);
94
+ };
95
+ var slow_down_default = slowDown;
96
+ export {
97
+ slow_down_default as default,
98
+ slowDown
99
+ };
package/license.md ADDED
@@ -0,0 +1,20 @@
1
+ # MIT License
2
+
3
+ Copyright 2023 Nathan Friedly, Vedant K
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/package.json ADDED
@@ -0,0 +1,162 @@
1
+ {
2
+ "name": "@depup/express-slow-down",
3
+ "version": "3.1.0-depup.0",
4
+ "description": "Basic IP rate-limiting middleware for Express that slows down responses rather than blocking the user. (with updated dependencies)",
5
+ "homepage": "https://github.com/express-rate-limit/express-slow-down",
6
+ "author": {
7
+ "name": "Nathan Friedly",
8
+ "url": "http://nfriedly.com/"
9
+ },
10
+ "license": "MIT",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/express-rate-limit/express-slow-down.git"
14
+ },
15
+ "keywords": [
16
+ "express-slow-down",
17
+ "depup",
18
+ "updated-dependencies",
19
+ "security",
20
+ "latest",
21
+ "patched",
22
+ "express-rate-limit",
23
+ "express",
24
+ "rate",
25
+ "limit",
26
+ "ratelimit",
27
+ "rate-limit",
28
+ "middleware",
29
+ "ip",
30
+ "auth",
31
+ "authorization",
32
+ "brute",
33
+ "force",
34
+ "bruteforce",
35
+ "brute-force",
36
+ "attack"
37
+ ],
38
+ "type": "module",
39
+ "exports": {
40
+ ".": {
41
+ "import": {
42
+ "types": "./dist/index.d.mts",
43
+ "default": "./dist/index.mjs"
44
+ },
45
+ "require": {
46
+ "types": "./dist/index.d.cts",
47
+ "default": "./dist/index.cjs"
48
+ }
49
+ }
50
+ },
51
+ "main": "dist/index.cjs",
52
+ "module": "./dist/index.mjs",
53
+ "types": "./dist/index.d.ts",
54
+ "files": [
55
+ "dist/",
56
+ "tsconfig.json",
57
+ "readme.md",
58
+ "license.md",
59
+ "changelog.md",
60
+ "changes.json",
61
+ "README.md"
62
+ ],
63
+ "engines": {
64
+ "node": ">= 16"
65
+ },
66
+ "scripts": {
67
+ "clean": "del-cli dist/ coverage/ *.log *.tmp *.bak *.tgz",
68
+ "build:cjs": "esbuild --platform=node --bundle --target=es2022 --packages=external --format=cjs --outfile=dist/index.cjs --footer:js=\"module.exports = slowDown; module.exports.default = slowDown; module.exports.slowDown = slowDown; \" source/index.ts",
69
+ "build:esm": "esbuild --platform=node --bundle --target=es2022 --packages=external --format=esm --outfile=dist/index.mjs source/index.ts",
70
+ "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",
71
+ "compile": "run-s clean build:*",
72
+ "lint:code": "xo",
73
+ "lint:rest": "prettier --check .",
74
+ "lint": "run-s lint:*",
75
+ "format:code": "xo --fix",
76
+ "format:rest": "prettier --write .",
77
+ "format": "run-s format:*",
78
+ "test:lib": "jest test/library/",
79
+ "test:int": "jest test/integration/",
80
+ "test": "run-s lint test:*",
81
+ "pre-commit": "lint-staged"
82
+ },
83
+ "peerDependencies": {
84
+ "express": "4 || 5 || ^5.0.0-beta.1"
85
+ },
86
+ "dependencies": {
87
+ "express-rate-limit": "^8.3.1"
88
+ },
89
+ "devDependencies": {
90
+ "@express-rate-limit/prettier": "1.1.1",
91
+ "@express-rate-limit/tsconfig": "1.0.2",
92
+ "@jest/globals": "29.7.0",
93
+ "@types/express": "4.17.18",
94
+ "@types/jest": "29.5.5",
95
+ "@types/supertest": "2.0.12",
96
+ "body-parser": "1.20.3",
97
+ "del-cli": "5.1.0",
98
+ "dts-bundle-generator": "8.0.1",
99
+ "esbuild": "0.25.0",
100
+ "express": "4.21.2",
101
+ "husky": "8.0.3",
102
+ "jest": "29.7.0",
103
+ "jest-expect-message": "1.1.3",
104
+ "lint-staged": "16.1.2",
105
+ "npm-run-all": "4.1.5",
106
+ "prettier": "3.0.3",
107
+ "supertest": "6.3.3",
108
+ "ts-jest": "29.1.1",
109
+ "typescript": "5.2.2",
110
+ "xo": "0.56.0"
111
+ },
112
+ "xo": {
113
+ "prettier": true,
114
+ "rules": {
115
+ "@typescript-eslint/prefer-nullish-coalescing": [
116
+ "error",
117
+ {
118
+ "ignoreConditionalTests": true
119
+ }
120
+ ],
121
+ "@typescript-eslint/no-confusing-void-expression": 0,
122
+ "@typescript-eslint/consistent-indexed-object-style": [
123
+ "error",
124
+ "index-signature"
125
+ ],
126
+ "unicorn/prefer-string-replace-all": 0
127
+ },
128
+ "overrides": [
129
+ {
130
+ "files": "test/**/*.ts",
131
+ "rules": {
132
+ "@typescript-eslint/no-unsafe-argument": 0,
133
+ "@typescript-eslint/no-unsafe-assignment": 0,
134
+ "@typescript-eslint/no-unsafe-call": 0,
135
+ "@typescript-eslint/no-unsafe-return": 0,
136
+ "@typescript-eslint/no-empty-function": 0,
137
+ "import/no-named-as-default": 0,
138
+ "unicorn/prefer-event-target": 0,
139
+ "unicorn/prevent-abbreviations": 0
140
+ }
141
+ }
142
+ ]
143
+ },
144
+ "prettier": "@express-rate-limit/prettier",
145
+ "lint-staged": {
146
+ "{source,test}/**/*.ts": "xo --fix",
147
+ "**/*.{json,yaml,md}": "prettier --write"
148
+ },
149
+ "depup": {
150
+ "changes": {
151
+ "express-rate-limit": {
152
+ "from": "8",
153
+ "to": "^8.3.1"
154
+ }
155
+ },
156
+ "depsUpdated": 1,
157
+ "originalPackage": "express-slow-down",
158
+ "originalVersion": "3.1.0",
159
+ "processedAt": "2026-03-19T03:04:02.971Z",
160
+ "smokeTest": "passed"
161
+ }
162
+ }
package/readme.md ADDED
@@ -0,0 +1,283 @@
1
+ # <div align="center"> Express Slow Down </div>
2
+
3
+ <div align="center">
4
+
5
+ [![tests](https://github.com/express-rate-limit/express-slow-down/actions/workflows/ci.yaml/badge.svg)](https://github.com/express-rate-limit/express-slow-down/actions/workflows/ci.yaml)
6
+ [![npm version](https://img.shields.io/npm/v/express-slow-down.svg)](https://npmjs.org/package/express-slow-down 'View this project on NPM')
7
+ [![npm downloads](https://img.shields.io/npm/dm/express-slow-down)](https://www.npmjs.com/package/express-slow-down)
8
+
9
+ Basic rate-limiting middleware for Express that slows down responses rather than
10
+ blocking them outright. Use to slow repeated requests to public APIs and/or
11
+ endpoints such as password reset.
12
+
13
+ Plays nice with (and built on top of)
14
+ [Express Rate Limit](https://npmjs.org/package/express-rate-limit)
15
+
16
+ </div>
17
+
18
+ ### Stores
19
+
20
+ The default memory store does not share state with any other processes or
21
+ servers. It's sufficient for basic abuse prevention, but an external store will
22
+ provide more consistency.
23
+
24
+ express-slow-down uses
25
+ [express-rate-limit's stores](https://express-rate-limit.mintlify.app/reference/stores)
26
+
27
+ > **Note**: when using express-slow-down and express-rate-limit with an external
28
+ > store, you'll need to create two instances of the store and provide different
29
+ > prefixes so that they don't double-count requests.
30
+
31
+ ## Installation
32
+
33
+ From the npm registry:
34
+
35
+ ```sh
36
+ # Using npm
37
+ > npm install express-slow-down
38
+ # Using yarn or pnpm
39
+ > yarn/pnpm add express-slow-down
40
+ ```
41
+
42
+ From Github Releases:
43
+
44
+ ```sh
45
+ # Using npm
46
+ > npm install https://github.com/express-rate-limit/express-slow-down/releases/download/v{version}/express-slow-down.tgz
47
+ # Using yarn or pnpm
48
+ > yarn/pnpm add https://github.com/express-rate-limit/express-slow-down/releases/download/v{version}/express-slow-down.tgz
49
+ ```
50
+
51
+ Replace `{version}` with the version of the package that you want to your, e.g.:
52
+ `2.0.0`.
53
+
54
+ ## Usage
55
+
56
+ ### Importing
57
+
58
+ This library is provided in ESM as well as CJS forms, and works with both
59
+ Javascript and Typescript projects.
60
+
61
+ **This package requires you to use Node 16 or above.**
62
+
63
+ Import it in a CommonJS project (`type: commonjs` or no `type` field in
64
+ `package.json`) as follows:
65
+
66
+ ```ts
67
+ const { slowDown } = require('express-slow-down')
68
+ ```
69
+
70
+ Import it in a ESM project (`type: module` in `package.json`) as follows:
71
+
72
+ ```ts
73
+ import { slowDown } from 'express-slow-down'
74
+ ```
75
+
76
+ ### Examples
77
+
78
+ To use it in an API-only server where the speed-limiter should be applied to all
79
+ requests:
80
+
81
+ ```ts
82
+ import { slowDown } from 'express-slow-down'
83
+
84
+ const limiter = slowDown({
85
+ windowMs: 15 * 60 * 1000, // 15 minutes
86
+ delayAfter: 5, // Allow 5 requests per 15 minutes.
87
+ delayMs: (hits) => hits * 100, // Add 100 ms of delay to every request after the 5th one.
88
+
89
+ /**
90
+ * So:
91
+ *
92
+ * - requests 1-5 are not delayed.
93
+ * - request 6 is delayed by 600ms
94
+ * - request 7 is delayed by 700ms
95
+ * - request 8 is delayed by 800ms
96
+ *
97
+ * and so on. After 15 minutes, the delay is reset to 0.
98
+ */
99
+ })
100
+
101
+ // Apply the delay middleware to all requests.
102
+ app.use(limiter)
103
+ ```
104
+
105
+ To use it in a 'regular' web server (e.g. anything that uses
106
+ `express.static()`), where the rate-limiter should only apply to certain
107
+ requests:
108
+
109
+ ```ts
110
+ import { slowDown } from 'express-slow-down'
111
+
112
+ const apiLimiter = slowDown({
113
+ windowMs: 15 * 60 * 1000, // 15 minutes
114
+ delayAfter: 1, // Allow only one request to go at full-speed.
115
+ delayMs: (hits) => hits * hits * 1000, // 2nd request has a 4 second delay, 3rd is 9 seconds, 4th is 16, etc.
116
+ })
117
+
118
+ // Apply the delay middleware to API calls only.
119
+ app.use('/api', apiLimiter)
120
+ ```
121
+
122
+ To use a custom store:
123
+
124
+ ```ts
125
+ import { slowDown } from 'express-slow-down'
126
+ import { MemcachedStore } from 'rate-limit-memcached'
127
+
128
+ const speedLimiter = slowDown({
129
+ windowMs: 15 * 60 * 1000, // 15 minutes
130
+ delayAfter: 1, // Allow only one request to go at full-speed.
131
+ delayMs: (hits) => hits * hits * 1000, // Add exponential delay after 1 request.
132
+ store: new MemcachedStore({
133
+ /* ... */
134
+ }), // Use the external store
135
+ })
136
+
137
+ // Apply the rate limiting middleware to all requests.
138
+ app.use(speedLimiter)
139
+ ```
140
+
141
+ > **Note:** most stores will require additional configuration, such as custom
142
+ > prefixes, when using multiple instances. The default built-in memory store is
143
+ > an exception to this rule.
144
+
145
+ ## Configuration
146
+
147
+ ### [`windowMs`](https://express-rate-limit.mintlify.app/reference/configuration#windowms)
148
+
149
+ > `number`
150
+
151
+ Time frame for which requests are checked/remembered.
152
+
153
+ Note that some stores have to be passed the value manually, while others infer
154
+ it from the options passed to this middleware.
155
+
156
+ Defaults to `60000` ms (= 1 minute).
157
+
158
+ ### `delayAfter`
159
+
160
+ > `number` | `function`
161
+
162
+ The max number of requests allowed during `windowMs` before the middleware
163
+ starts delaying responses. Can be the limit itself as a number or a (sync/async)
164
+ function that accepts the Express `req` and `res` objects and then returns a
165
+ number.
166
+
167
+ Defaults to `1`.
168
+
169
+ An example of using a function:
170
+
171
+ ```ts
172
+ const isPremium = async (user) => {
173
+ // ...
174
+ }
175
+
176
+ const limiter = slowDown({
177
+ // ...
178
+ delayAfter: async (req, res) => {
179
+ if (await isPremium(req.user)) return 10
180
+ else return 1
181
+ },
182
+ })
183
+ ```
184
+
185
+ ### `delayMs`
186
+
187
+ > `number | function`
188
+
189
+ The delay to apply to each request once the limit is reached. Can be the delay
190
+ itself (in milliseconds) as a number or a (sync/async) function that accepts a
191
+ number (number of requests in the current window), the Express `req` and `res`
192
+ objects and then returns a number.
193
+
194
+ By default, it increases the delay by 1 second for every request over the limit:
195
+
196
+ ```ts
197
+ const limiter = slowDown({
198
+ // ...
199
+ delayMs: (used) => (used - delayAfter) * 1000,
200
+ })
201
+ ```
202
+
203
+ ### `maxDelayMs`
204
+
205
+ > `number | function`
206
+
207
+ The absolute maximum value for `delayMs`. After many consecutive attempts, the
208
+ delay will always be this value. This option should be used especially when your
209
+ application is running behind a load balancer or reverse proxy that has a
210
+ request timeout. Can be the number itself (in milliseconds) or a (sync/async)
211
+ function that accepts the Express `req` and `res` objects and then returns a
212
+ number.
213
+
214
+ Defaults to `Infinity`.
215
+
216
+ For example, for the following configuration:
217
+
218
+ ```ts
219
+ const limiter = slowDown({
220
+ // ...
221
+ delayAfter: 1,
222
+ delayMs: (hits) => hits * 1000,
223
+ maxDelayMs: 4000,
224
+ })
225
+ ```
226
+
227
+ The first request will have no delay. The second will have a 2 second delay, the
228
+ 3rd will have a 3 second delay, but the fourth, fifth, sixth, seventh and so on
229
+ requests will all have a 4 second delay.
230
+
231
+ ### Options from [`express-rate-limit`](https://github.com/express-rate-limit/express-rate-limit)
232
+
233
+ Because
234
+ [`express-rate-limit`](https://github.com/express-rate-limit/express-rate-limit)
235
+ is used internally, additional options that it supports may be passed in. Some
236
+ of them are listed below; see `express-rate-limit`'s
237
+ [documentation](https://express-rate-limit.mintlify.app/reference/configuration)
238
+ for the complete list.
239
+
240
+ > **Note**: The `limit` (`max`) option is not supported (use `delayAfter`
241
+ > instead), nor is the `handler` option.
242
+
243
+ - [`standardHeaders`](https://express-rate-limit.mintlify.app/reference/configuration#standardheaders)
244
+ - [`legacyHeaders`](https://express-rate-limit.mintlify.app/reference/configuration#legacyheaders)
245
+ - [`requestPropertyName`](https://express-rate-limit.mintlify.app/reference/configuration#requestpropertyname)
246
+ - [`skipFailedRequests`](https://express-rate-limit.mintlify.app/reference/configuration#skipfailedrequests)
247
+ - [`skipSuccessfulRequests`](https://express-rate-limit.mintlify.app/reference/configuration#skipsuccessfulrequests)
248
+ - [`keyGenerator`](https://express-rate-limit.mintlify.app/reference/configuration#keygenerator)
249
+ - [`ipv6Subnet`](https://express-rate-limit.mintlify.app/reference/configuration#ipv6subnet)
250
+ - [`skip`](https://express-rate-limit.mintlify.app/reference/configuration#skip)
251
+ - [`requestWasSuccessful`](https://express-rate-limit.mintlify.app/reference/configuration#requestwassuccessful)
252
+ - [`validate`](https://express-rate-limit.mintlify.app/reference/configuration#validate)
253
+ - [`store`](https://express-rate-limit.mintlify.app/reference/configuration#store)
254
+
255
+ ## Request API
256
+
257
+ A `req.slowDown` property is added to all requests with the `limit`, `used`, and
258
+ `remaining` number of requests and, if the store provides it, a `resetTime` Date
259
+ object. It also has the `delay` property, which is the amount of delay imposed
260
+ on current request (milliseconds). These may be used in your application code to
261
+ take additional actions or inform the user of their status.
262
+
263
+ Note that `used` includes the current request, so it should always be > 0.
264
+
265
+ The property name can be configured with the configuration option
266
+ `requestPropertyName`.
267
+
268
+ ## Issues and Contributing
269
+
270
+ If you encounter a bug or want to see something added/changed, please go ahead
271
+ and
272
+ [open an issue](https://github.com/express-rate-limit/express-slow-down/issues/new)!
273
+ If you need help with something, feel free to
274
+ [start a discussion](https://github.com/express-rate-limit/express-slow-down/discussions/new)!
275
+
276
+ If you wish to contribute to the library, thanks! First, please read
277
+ [the contributing guide](contributing.md). Then you can pick up any issue and
278
+ fix/implement it!
279
+
280
+ ## License
281
+
282
+ MIT © [Nathan Friedly](http://nfriedly.com/),
283
+ [Vedant K](https://github.com/gamemaker1)
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "@express-rate-limit/tsconfig",
3
+ "include": ["source/"],
4
+ "exclude": ["node_modules/"],
5
+ "compilerOptions": {
6
+ "target": "ES2020",
7
+ "outDir": "dist"
8
+ }
9
+ }