express-rate-limit 8.5.1 → 8.6.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/dist/index.cjs +70 -6
- package/dist/index.d.cts +18 -0
- package/dist/index.d.mts +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.mjs +56 -6
- package/package.json +13 -10
- package/readme.md +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,12 +17,24 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// source/index.ts
|
|
21
31
|
var index_exports = {};
|
|
22
32
|
__export(index_exports, {
|
|
33
|
+
DAY: () => DAY,
|
|
34
|
+
HOUR: () => HOUR,
|
|
35
|
+
MINUTE: () => MINUTE,
|
|
23
36
|
MemoryStore: () => MemoryStore,
|
|
37
|
+
SECOND: () => SECOND,
|
|
24
38
|
default: () => rate_limit_default,
|
|
25
39
|
ipKeyGenerator: () => ipKeyGenerator,
|
|
26
40
|
rateLimit: () => rate_limit_default
|
|
@@ -36,7 +50,7 @@ function ipKeyGenerator(ip, ipv6Subnet = 56) {
|
|
|
36
50
|
if (address.is4()) return address.to4().correctForm();
|
|
37
51
|
if (ipv6Subnet) {
|
|
38
52
|
const subnet = new import_ip_address.Address6(`${ip}/${ipv6Subnet}`);
|
|
39
|
-
return
|
|
53
|
+
return subnet.networkForm();
|
|
40
54
|
}
|
|
41
55
|
}
|
|
42
56
|
return ip;
|
|
@@ -200,6 +214,7 @@ var MemoryStore = class {
|
|
|
200
214
|
|
|
201
215
|
// source/rate-limit.ts
|
|
202
216
|
var import_node_net3 = require("node:net");
|
|
217
|
+
var import_debug = __toESM(require("debug"), 1);
|
|
203
218
|
|
|
204
219
|
// source/console-logger.ts
|
|
205
220
|
var ConsoleLogger = {
|
|
@@ -699,6 +714,7 @@ var getValidations = (_enabled, logger) => {
|
|
|
699
714
|
if (!(enabled[name] ?? enabled.default)) {
|
|
700
715
|
return;
|
|
701
716
|
}
|
|
717
|
+
enabled[name] = false;
|
|
702
718
|
try {
|
|
703
719
|
;
|
|
704
720
|
validation.apply(
|
|
@@ -711,6 +727,9 @@ var getValidations = (_enabled, logger) => {
|
|
|
711
727
|
}
|
|
712
728
|
};
|
|
713
729
|
}
|
|
730
|
+
const inspect = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
|
|
731
|
+
if (inspect)
|
|
732
|
+
wrappedValidations[inspect] = () => wrappedValidations.enabled;
|
|
714
733
|
return wrappedValidations;
|
|
715
734
|
};
|
|
716
735
|
|
|
@@ -859,9 +878,14 @@ var handleAsyncErrors = (fn) => async (request, response, next) => {
|
|
|
859
878
|
var rateLimit = (passedOptions) => {
|
|
860
879
|
const config = parseOptions(passedOptions ?? {});
|
|
861
880
|
const options = getOptionsFromConfig(config);
|
|
881
|
+
const debug = (0, import_debug.default)("express-rate-limit");
|
|
882
|
+
debug("creating new rate limiter with %o", config.store.constructor.name);
|
|
883
|
+
for (const [key, val] of Object.entries(config))
|
|
884
|
+
debug("set %s to %o", key, val);
|
|
862
885
|
config.validations.creationStack(config.store);
|
|
863
886
|
config.validations.unsharedStore(config.store);
|
|
864
887
|
if (typeof config.store.init === "function") {
|
|
888
|
+
debug("executing init for store");
|
|
865
889
|
try {
|
|
866
890
|
const storeInit = config.store.init(options);
|
|
867
891
|
if (storeInit instanceof Promise) {
|
|
@@ -884,13 +908,18 @@ var rateLimit = (passedOptions) => {
|
|
|
884
908
|
const closePromise = config.skipFailedRequests && new Promise((resolve) => response.once("close", resolve));
|
|
885
909
|
const finishPromise = (config.skipFailedRequests || config.skipSuccessfulRequests) && new Promise((resolve) => response.once("finish", resolve));
|
|
886
910
|
const errorPromise = config.skipFailedRequests && new Promise((resolve) => response.once("error", resolve));
|
|
911
|
+
debug("requested %o", request.originalUrl);
|
|
912
|
+
debug("request from ip %o", request.ip);
|
|
887
913
|
const skip = await config.skip(request, response);
|
|
888
914
|
if (skip) {
|
|
915
|
+
debug("skipping request");
|
|
889
916
|
next();
|
|
890
917
|
return;
|
|
891
918
|
}
|
|
892
919
|
const augmentedRequest = request;
|
|
893
920
|
const key = await config.keyGenerator(request, response);
|
|
921
|
+
debug("computed key %o", key);
|
|
922
|
+
debug("incrementing count");
|
|
894
923
|
let totalHits = 0;
|
|
895
924
|
let resetTime;
|
|
896
925
|
try {
|
|
@@ -920,6 +949,13 @@ var rateLimit = (passedOptions) => {
|
|
|
920
949
|
resetTime,
|
|
921
950
|
key
|
|
922
951
|
};
|
|
952
|
+
for (const [key2, val] of Object.entries(info))
|
|
953
|
+
debug(
|
|
954
|
+
"set request.%s.%s to be %o",
|
|
955
|
+
config.requestPropertyName,
|
|
956
|
+
key2,
|
|
957
|
+
val
|
|
958
|
+
);
|
|
923
959
|
Object.defineProperty(info, "current", {
|
|
924
960
|
configurable: false,
|
|
925
961
|
enumerable: false,
|
|
@@ -927,15 +963,18 @@ var rateLimit = (passedOptions) => {
|
|
|
927
963
|
});
|
|
928
964
|
augmentedRequest[config.requestPropertyName] = info;
|
|
929
965
|
if (config.legacyHeaders && !response.headersSent) {
|
|
966
|
+
debug("set legacy headers");
|
|
930
967
|
setLegacyHeaders(response, info);
|
|
931
968
|
}
|
|
932
969
|
if (config.standardHeaders && !response.headersSent) {
|
|
933
970
|
switch (config.standardHeaders) {
|
|
934
971
|
case "draft-6": {
|
|
972
|
+
debug("set ietf draft 6 headers");
|
|
935
973
|
setDraft6Headers(response, info, config.windowMs);
|
|
936
974
|
break;
|
|
937
975
|
}
|
|
938
976
|
case "draft-7": {
|
|
977
|
+
debug("set ietf draft 7 headers");
|
|
939
978
|
config.validations.headersResetTime(info.resetTime);
|
|
940
979
|
setDraft7Headers(response, info, config.windowMs);
|
|
941
980
|
break;
|
|
@@ -943,6 +982,8 @@ var rateLimit = (passedOptions) => {
|
|
|
943
982
|
case "draft-8": {
|
|
944
983
|
const retrieveName = typeof config.identifier === "function" ? config.identifier(request, response) : config.identifier;
|
|
945
984
|
const name = await retrieveName;
|
|
985
|
+
debug("set ietf draft 8 headers");
|
|
986
|
+
debug("set name to %o", name);
|
|
946
987
|
config.validations.headersResetTime(info.resetTime);
|
|
947
988
|
setDraft8Headers(response, info, config.windowMs, name, key);
|
|
948
989
|
break;
|
|
@@ -957,6 +998,10 @@ var rateLimit = (passedOptions) => {
|
|
|
957
998
|
let decremented = false;
|
|
958
999
|
const decrementKey = async () => {
|
|
959
1000
|
if (!decremented) {
|
|
1001
|
+
if (resetTime && Date.now() >= resetTime.getTime()) {
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
debug("decrementing count");
|
|
960
1005
|
await config.store.decrement(key);
|
|
961
1006
|
decremented = true;
|
|
962
1007
|
}
|
|
@@ -964,8 +1009,12 @@ var rateLimit = (passedOptions) => {
|
|
|
964
1009
|
if (config.skipFailedRequests) {
|
|
965
1010
|
if (finishPromise) {
|
|
966
1011
|
void finishPromise.then(async () => {
|
|
967
|
-
|
|
968
|
-
|
|
1012
|
+
const success = await config.requestWasSuccessful(
|
|
1013
|
+
request,
|
|
1014
|
+
response
|
|
1015
|
+
);
|
|
1016
|
+
debug("computed requestWasSuccessful as %o", success);
|
|
1017
|
+
if (!success) await decrementKey();
|
|
969
1018
|
});
|
|
970
1019
|
}
|
|
971
1020
|
if (closePromise) {
|
|
@@ -982,15 +1031,20 @@ var rateLimit = (passedOptions) => {
|
|
|
982
1031
|
if (config.skipSuccessfulRequests) {
|
|
983
1032
|
if (finishPromise) {
|
|
984
1033
|
void finishPromise.then(async () => {
|
|
985
|
-
|
|
986
|
-
|
|
1034
|
+
const success = await config.requestWasSuccessful(
|
|
1035
|
+
request,
|
|
1036
|
+
response
|
|
1037
|
+
);
|
|
1038
|
+
debug("computed requestWasSuccessful as %o", success);
|
|
1039
|
+
if (success) await decrementKey();
|
|
987
1040
|
});
|
|
988
1041
|
}
|
|
989
1042
|
}
|
|
990
1043
|
}
|
|
991
|
-
config.validations.disable();
|
|
992
1044
|
if (totalHits > limit) {
|
|
1045
|
+
debug("limit exceeded");
|
|
993
1046
|
if (config.legacyHeaders || config.standardHeaders) {
|
|
1047
|
+
debug("set retry-after header");
|
|
994
1048
|
setRetryAfterHeader(response, info, config.windowMs);
|
|
995
1049
|
}
|
|
996
1050
|
config.handler(request, response, next, options);
|
|
@@ -1007,9 +1061,19 @@ var rateLimit = (passedOptions) => {
|
|
|
1007
1061
|
return middleware;
|
|
1008
1062
|
};
|
|
1009
1063
|
var rate_limit_default = rateLimit;
|
|
1064
|
+
|
|
1065
|
+
// source/time-constants.ts
|
|
1066
|
+
var SECOND = 1e3;
|
|
1067
|
+
var MINUTE = 60 * SECOND;
|
|
1068
|
+
var HOUR = 60 * MINUTE;
|
|
1069
|
+
var DAY = 24 * HOUR;
|
|
1010
1070
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1011
1071
|
0 && (module.exports = {
|
|
1072
|
+
DAY,
|
|
1073
|
+
HOUR,
|
|
1074
|
+
MINUTE,
|
|
1012
1075
|
MemoryStore,
|
|
1076
|
+
SECOND,
|
|
1013
1077
|
ipKeyGenerator,
|
|
1014
1078
|
rateLimit
|
|
1015
1079
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -664,6 +664,24 @@ export declare class MemoryStore implements Store {
|
|
|
664
664
|
* @public
|
|
665
665
|
*/
|
|
666
666
|
export declare const rateLimit: (passedOptions?: Partial<Options>) => RateLimitRequestHandler;
|
|
667
|
+
/**
|
|
668
|
+
* Time constants in milliseconds
|
|
669
|
+
*
|
|
670
|
+
* Use these with rate limit window calculations:
|
|
671
|
+
* @example
|
|
672
|
+
* // 5 minute window
|
|
673
|
+
* windowMs: 5 * MINUTE
|
|
674
|
+
*
|
|
675
|
+
* // 2 hour window
|
|
676
|
+
* windowMs: 2 * HOUR
|
|
677
|
+
*
|
|
678
|
+
* // 1 day window
|
|
679
|
+
* windowMs: 1 * DAY
|
|
680
|
+
*/
|
|
681
|
+
export declare const SECOND: number;
|
|
682
|
+
export declare const MINUTE: number;
|
|
683
|
+
export declare const HOUR: number;
|
|
684
|
+
export declare const DAY: number;
|
|
667
685
|
|
|
668
686
|
export {
|
|
669
687
|
rateLimit as default,
|
package/dist/index.d.mts
CHANGED
|
@@ -664,6 +664,24 @@ export declare class MemoryStore implements Store {
|
|
|
664
664
|
* @public
|
|
665
665
|
*/
|
|
666
666
|
export declare const rateLimit: (passedOptions?: Partial<Options>) => RateLimitRequestHandler;
|
|
667
|
+
/**
|
|
668
|
+
* Time constants in milliseconds
|
|
669
|
+
*
|
|
670
|
+
* Use these with rate limit window calculations:
|
|
671
|
+
* @example
|
|
672
|
+
* // 5 minute window
|
|
673
|
+
* windowMs: 5 * MINUTE
|
|
674
|
+
*
|
|
675
|
+
* // 2 hour window
|
|
676
|
+
* windowMs: 2 * HOUR
|
|
677
|
+
*
|
|
678
|
+
* // 1 day window
|
|
679
|
+
* windowMs: 1 * DAY
|
|
680
|
+
*/
|
|
681
|
+
export declare const SECOND: number;
|
|
682
|
+
export declare const MINUTE: number;
|
|
683
|
+
export declare const HOUR: number;
|
|
684
|
+
export declare const DAY: number;
|
|
667
685
|
|
|
668
686
|
export {
|
|
669
687
|
rateLimit as default,
|
package/dist/index.d.ts
CHANGED
|
@@ -664,6 +664,24 @@ export declare class MemoryStore implements Store {
|
|
|
664
664
|
* @public
|
|
665
665
|
*/
|
|
666
666
|
export declare const rateLimit: (passedOptions?: Partial<Options>) => RateLimitRequestHandler;
|
|
667
|
+
/**
|
|
668
|
+
* Time constants in milliseconds
|
|
669
|
+
*
|
|
670
|
+
* Use these with rate limit window calculations:
|
|
671
|
+
* @example
|
|
672
|
+
* // 5 minute window
|
|
673
|
+
* windowMs: 5 * MINUTE
|
|
674
|
+
*
|
|
675
|
+
* // 2 hour window
|
|
676
|
+
* windowMs: 2 * HOUR
|
|
677
|
+
*
|
|
678
|
+
* // 1 day window
|
|
679
|
+
* windowMs: 1 * DAY
|
|
680
|
+
*/
|
|
681
|
+
export declare const SECOND: number;
|
|
682
|
+
export declare const MINUTE: number;
|
|
683
|
+
export declare const HOUR: number;
|
|
684
|
+
export declare const DAY: number;
|
|
667
685
|
|
|
668
686
|
export {
|
|
669
687
|
rateLimit as default,
|
package/dist/index.mjs
CHANGED
|
@@ -7,7 +7,7 @@ function ipKeyGenerator(ip, ipv6Subnet = 56) {
|
|
|
7
7
|
if (address.is4()) return address.to4().correctForm();
|
|
8
8
|
if (ipv6Subnet) {
|
|
9
9
|
const subnet = new Address6(`${ip}/${ipv6Subnet}`);
|
|
10
|
-
return
|
|
10
|
+
return subnet.networkForm();
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
return ip;
|
|
@@ -171,6 +171,7 @@ var MemoryStore = class {
|
|
|
171
171
|
|
|
172
172
|
// source/rate-limit.ts
|
|
173
173
|
import { isIPv6 as isIPv62 } from "node:net";
|
|
174
|
+
import createDebugLogger from "debug";
|
|
174
175
|
|
|
175
176
|
// source/console-logger.ts
|
|
176
177
|
var ConsoleLogger = {
|
|
@@ -670,6 +671,7 @@ var getValidations = (_enabled, logger) => {
|
|
|
670
671
|
if (!(enabled[name] ?? enabled.default)) {
|
|
671
672
|
return;
|
|
672
673
|
}
|
|
674
|
+
enabled[name] = false;
|
|
673
675
|
try {
|
|
674
676
|
;
|
|
675
677
|
validation.apply(
|
|
@@ -682,6 +684,9 @@ var getValidations = (_enabled, logger) => {
|
|
|
682
684
|
}
|
|
683
685
|
};
|
|
684
686
|
}
|
|
687
|
+
const inspect = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
|
|
688
|
+
if (inspect)
|
|
689
|
+
wrappedValidations[inspect] = () => wrappedValidations.enabled;
|
|
685
690
|
return wrappedValidations;
|
|
686
691
|
};
|
|
687
692
|
|
|
@@ -830,9 +835,14 @@ var handleAsyncErrors = (fn) => async (request, response, next) => {
|
|
|
830
835
|
var rateLimit = (passedOptions) => {
|
|
831
836
|
const config = parseOptions(passedOptions ?? {});
|
|
832
837
|
const options = getOptionsFromConfig(config);
|
|
838
|
+
const debug = createDebugLogger("express-rate-limit");
|
|
839
|
+
debug("creating new rate limiter with %o", config.store.constructor.name);
|
|
840
|
+
for (const [key, val] of Object.entries(config))
|
|
841
|
+
debug("set %s to %o", key, val);
|
|
833
842
|
config.validations.creationStack(config.store);
|
|
834
843
|
config.validations.unsharedStore(config.store);
|
|
835
844
|
if (typeof config.store.init === "function") {
|
|
845
|
+
debug("executing init for store");
|
|
836
846
|
try {
|
|
837
847
|
const storeInit = config.store.init(options);
|
|
838
848
|
if (storeInit instanceof Promise) {
|
|
@@ -855,13 +865,18 @@ var rateLimit = (passedOptions) => {
|
|
|
855
865
|
const closePromise = config.skipFailedRequests && new Promise((resolve) => response.once("close", resolve));
|
|
856
866
|
const finishPromise = (config.skipFailedRequests || config.skipSuccessfulRequests) && new Promise((resolve) => response.once("finish", resolve));
|
|
857
867
|
const errorPromise = config.skipFailedRequests && new Promise((resolve) => response.once("error", resolve));
|
|
868
|
+
debug("requested %o", request.originalUrl);
|
|
869
|
+
debug("request from ip %o", request.ip);
|
|
858
870
|
const skip = await config.skip(request, response);
|
|
859
871
|
if (skip) {
|
|
872
|
+
debug("skipping request");
|
|
860
873
|
next();
|
|
861
874
|
return;
|
|
862
875
|
}
|
|
863
876
|
const augmentedRequest = request;
|
|
864
877
|
const key = await config.keyGenerator(request, response);
|
|
878
|
+
debug("computed key %o", key);
|
|
879
|
+
debug("incrementing count");
|
|
865
880
|
let totalHits = 0;
|
|
866
881
|
let resetTime;
|
|
867
882
|
try {
|
|
@@ -891,6 +906,13 @@ var rateLimit = (passedOptions) => {
|
|
|
891
906
|
resetTime,
|
|
892
907
|
key
|
|
893
908
|
};
|
|
909
|
+
for (const [key2, val] of Object.entries(info))
|
|
910
|
+
debug(
|
|
911
|
+
"set request.%s.%s to be %o",
|
|
912
|
+
config.requestPropertyName,
|
|
913
|
+
key2,
|
|
914
|
+
val
|
|
915
|
+
);
|
|
894
916
|
Object.defineProperty(info, "current", {
|
|
895
917
|
configurable: false,
|
|
896
918
|
enumerable: false,
|
|
@@ -898,15 +920,18 @@ var rateLimit = (passedOptions) => {
|
|
|
898
920
|
});
|
|
899
921
|
augmentedRequest[config.requestPropertyName] = info;
|
|
900
922
|
if (config.legacyHeaders && !response.headersSent) {
|
|
923
|
+
debug("set legacy headers");
|
|
901
924
|
setLegacyHeaders(response, info);
|
|
902
925
|
}
|
|
903
926
|
if (config.standardHeaders && !response.headersSent) {
|
|
904
927
|
switch (config.standardHeaders) {
|
|
905
928
|
case "draft-6": {
|
|
929
|
+
debug("set ietf draft 6 headers");
|
|
906
930
|
setDraft6Headers(response, info, config.windowMs);
|
|
907
931
|
break;
|
|
908
932
|
}
|
|
909
933
|
case "draft-7": {
|
|
934
|
+
debug("set ietf draft 7 headers");
|
|
910
935
|
config.validations.headersResetTime(info.resetTime);
|
|
911
936
|
setDraft7Headers(response, info, config.windowMs);
|
|
912
937
|
break;
|
|
@@ -914,6 +939,8 @@ var rateLimit = (passedOptions) => {
|
|
|
914
939
|
case "draft-8": {
|
|
915
940
|
const retrieveName = typeof config.identifier === "function" ? config.identifier(request, response) : config.identifier;
|
|
916
941
|
const name = await retrieveName;
|
|
942
|
+
debug("set ietf draft 8 headers");
|
|
943
|
+
debug("set name to %o", name);
|
|
917
944
|
config.validations.headersResetTime(info.resetTime);
|
|
918
945
|
setDraft8Headers(response, info, config.windowMs, name, key);
|
|
919
946
|
break;
|
|
@@ -928,6 +955,10 @@ var rateLimit = (passedOptions) => {
|
|
|
928
955
|
let decremented = false;
|
|
929
956
|
const decrementKey = async () => {
|
|
930
957
|
if (!decremented) {
|
|
958
|
+
if (resetTime && Date.now() >= resetTime.getTime()) {
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
debug("decrementing count");
|
|
931
962
|
await config.store.decrement(key);
|
|
932
963
|
decremented = true;
|
|
933
964
|
}
|
|
@@ -935,8 +966,12 @@ var rateLimit = (passedOptions) => {
|
|
|
935
966
|
if (config.skipFailedRequests) {
|
|
936
967
|
if (finishPromise) {
|
|
937
968
|
void finishPromise.then(async () => {
|
|
938
|
-
|
|
939
|
-
|
|
969
|
+
const success = await config.requestWasSuccessful(
|
|
970
|
+
request,
|
|
971
|
+
response
|
|
972
|
+
);
|
|
973
|
+
debug("computed requestWasSuccessful as %o", success);
|
|
974
|
+
if (!success) await decrementKey();
|
|
940
975
|
});
|
|
941
976
|
}
|
|
942
977
|
if (closePromise) {
|
|
@@ -953,15 +988,20 @@ var rateLimit = (passedOptions) => {
|
|
|
953
988
|
if (config.skipSuccessfulRequests) {
|
|
954
989
|
if (finishPromise) {
|
|
955
990
|
void finishPromise.then(async () => {
|
|
956
|
-
|
|
957
|
-
|
|
991
|
+
const success = await config.requestWasSuccessful(
|
|
992
|
+
request,
|
|
993
|
+
response
|
|
994
|
+
);
|
|
995
|
+
debug("computed requestWasSuccessful as %o", success);
|
|
996
|
+
if (success) await decrementKey();
|
|
958
997
|
});
|
|
959
998
|
}
|
|
960
999
|
}
|
|
961
1000
|
}
|
|
962
|
-
config.validations.disable();
|
|
963
1001
|
if (totalHits > limit) {
|
|
1002
|
+
debug("limit exceeded");
|
|
964
1003
|
if (config.legacyHeaders || config.standardHeaders) {
|
|
1004
|
+
debug("set retry-after header");
|
|
965
1005
|
setRetryAfterHeader(response, info, config.windowMs);
|
|
966
1006
|
}
|
|
967
1007
|
config.handler(request, response, next, options);
|
|
@@ -978,8 +1018,18 @@ var rateLimit = (passedOptions) => {
|
|
|
978
1018
|
return middleware;
|
|
979
1019
|
};
|
|
980
1020
|
var rate_limit_default = rateLimit;
|
|
1021
|
+
|
|
1022
|
+
// source/time-constants.ts
|
|
1023
|
+
var SECOND = 1e3;
|
|
1024
|
+
var MINUTE = 60 * SECOND;
|
|
1025
|
+
var HOUR = 60 * MINUTE;
|
|
1026
|
+
var DAY = 24 * HOUR;
|
|
981
1027
|
export {
|
|
1028
|
+
DAY,
|
|
1029
|
+
HOUR,
|
|
1030
|
+
MINUTE,
|
|
982
1031
|
MemoryStore,
|
|
1032
|
+
SECOND,
|
|
983
1033
|
rate_limit_default as default,
|
|
984
1034
|
ipKeyGenerator,
|
|
985
1035
|
rate_limit_default as rateLimit
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "express-rate-limit",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.6.0",
|
|
4
4
|
"description": "Basic IP rate-limiting middleware for Express. Use to limit repeated requests to public APIs and/or endpoints such as password reset.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Nathan Friedly",
|
|
@@ -75,33 +75,36 @@
|
|
|
75
75
|
"prepare": "run-s compile && husky"
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
|
+
"debug": "^4.4.3",
|
|
78
79
|
"ip-address": "^10.2.0"
|
|
79
80
|
},
|
|
80
81
|
"peerDependencies": {
|
|
81
82
|
"express": ">= 4.11"
|
|
82
83
|
},
|
|
83
84
|
"devDependencies": {
|
|
85
|
+
"@asyncapi/specs": "6.8.1",
|
|
84
86
|
"@biomejs/biome": "2.4.6",
|
|
85
87
|
"@express-rate-limit/prettier": "1.1.1",
|
|
86
|
-
"@express-rate-limit/tsconfig": "1.0.
|
|
87
|
-
"@jest/globals": "30.
|
|
88
|
+
"@express-rate-limit/tsconfig": "1.0.5",
|
|
89
|
+
"@jest/globals": "30.4.1",
|
|
90
|
+
"@types/debug": "4.1.13",
|
|
88
91
|
"@types/express": "5.0.6",
|
|
89
92
|
"@types/jest": "30.0.0",
|
|
90
|
-
"@types/node": "
|
|
93
|
+
"@types/node": "26.1.1",
|
|
91
94
|
"@types/supertest": "7.2.0",
|
|
92
95
|
"del-cli": "7.0.0",
|
|
93
96
|
"dts-bundle-generator": "8.1.2",
|
|
94
|
-
"esbuild": "0.
|
|
97
|
+
"esbuild": "0.28.1",
|
|
95
98
|
"express": "5.2.1",
|
|
96
99
|
"husky": "9.1.7",
|
|
97
|
-
"jest": "30.
|
|
98
|
-
"lint-staged": "
|
|
99
|
-
"mintlify": "4.2.
|
|
100
|
+
"jest": "30.4.2",
|
|
101
|
+
"lint-staged": "17.0.8",
|
|
102
|
+
"mintlify": "4.2.688",
|
|
100
103
|
"npm-run-all": "4.1.5",
|
|
101
|
-
"prettier": "3.
|
|
104
|
+
"prettier": "3.9.5",
|
|
102
105
|
"ratelimit-header-parser": "0.1.0",
|
|
103
106
|
"supertest": "7.2.2",
|
|
104
|
-
"ts-jest": "29.4.
|
|
107
|
+
"ts-jest": "29.4.11",
|
|
105
108
|
"ts-node": "10.9.2",
|
|
106
109
|
"typescript": "5.9.3"
|
|
107
110
|
},
|
package/readme.md
CHANGED
|
@@ -21,10 +21,10 @@ The [full documentation](https://express-rate-limit.mintlify.app/overview) is
|
|
|
21
21
|
available on-line.
|
|
22
22
|
|
|
23
23
|
```ts
|
|
24
|
-
import { rateLimit } from 'express-rate-limit'
|
|
24
|
+
import { rateLimit, MINUTE } from 'express-rate-limit'
|
|
25
25
|
|
|
26
26
|
const limiter = rateLimit({
|
|
27
|
-
windowMs: 15 *
|
|
27
|
+
windowMs: 15 * MINUTE, // SECOND, MINUTE, HOUR, and DAY constants are available, or a use bare number for milliseconds
|
|
28
28
|
limit: 100, // Limit each IP to 100 requests per `window` (here, per 15 minutes).
|
|
29
29
|
standardHeaders: 'draft-8', // draft-6: `RateLimit-*` headers; draft-7 & draft-8: combined `RateLimit` header
|
|
30
30
|
legacyHeaders: false, // Disable the `X-RateLimit-*` headers.
|