rate-limiter-flexible 8.2.1 → 9.0.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 +2 -1
- package/index.js +2 -0
- package/lib/RLWrapperTimeouts.js +82 -0
- package/lib/RateLimiterInsuredAbstract.js +112 -0
- package/lib/RateLimiterMongo.js +2 -41
- package/lib/RateLimiterStoreAbstract.js +11 -46
- package/package.json +2 -2
- package/types.d.ts +15 -1
package/README.md
CHANGED
|
@@ -96,7 +96,7 @@ const headers = {
|
|
|
96
96
|
* no race conditions
|
|
97
97
|
* no production dependencies
|
|
98
98
|
* TypeScript declaration bundled
|
|
99
|
-
* Block Strategy against really powerful
|
|
99
|
+
* Block Strategy against really powerful DoS attacks (like 100k requests per sec) [Read about it and benchmarking here](https://github.com/animir/node-rate-limiter-flexible/wiki/In-memory-Block-Strategy)
|
|
100
100
|
* Insurance Strategy as emergency solution if database/store is down [Read about Insurance Strategy here](https://github.com/animir/node-rate-limiter-flexible/wiki/Insurance-Strategy)
|
|
101
101
|
* works in Cluster or PM2 without additional software [See RateLimiterCluster benchmark and detailed description here](https://github.com/animir/node-rate-limiter-flexible/wiki/Cluster)
|
|
102
102
|
* useful `get`, `set`, `block`, `delete`, `penalty` and `reward` methods
|
|
@@ -147,6 +147,7 @@ Some copy/paste examples on Wiki:
|
|
|
147
147
|
* [BurstyRateLimiter](https://github.com/animir/node-rate-limiter-flexible/wiki/BurstyRateLimiter) Traffic burst support
|
|
148
148
|
* [RateLimiterUnion](https://github.com/animir/node-rate-limiter-flexible/wiki/RateLimiterUnion) Combine 2 or more limiters to act as single
|
|
149
149
|
* [RLWrapperBlackAndWhite](https://github.com/animir/node-rate-limiter-flexible/wiki/Black-and-White-lists) Black and White lists
|
|
150
|
+
* [RLWrapperTimeouts](https://github.com/animir/node-rate-limiter-flexible/wiki/RLWrapperTimeouts) Timeouts
|
|
150
151
|
* [RateLimiterQueue](https://github.com/animir/node-rate-limiter-flexible/wiki/RateLimiterQueue) Rate limiter with FIFO queue
|
|
151
152
|
* [AWS SDK v3 Client Rate Limiter](https://github.com/animir/node-rate-limiter-flexible/wiki/AWS-SDK-v3-Client-Rate-Limiter) Prevent punishing rate limit.
|
|
152
153
|
|
package/index.js
CHANGED
|
@@ -6,6 +6,7 @@ const { RateLimiterClusterMaster, RateLimiterClusterMasterPM2, RateLimiterCluste
|
|
|
6
6
|
const RateLimiterMemory = require('./lib/RateLimiterMemory');
|
|
7
7
|
const RateLimiterMemcache = require('./lib/RateLimiterMemcache');
|
|
8
8
|
const RLWrapperBlackAndWhite = require('./lib/RLWrapperBlackAndWhite');
|
|
9
|
+
const RLWrapperTimeouts = require('./lib/RLWrapperTimeouts');
|
|
9
10
|
const RateLimiterUnion = require('./lib/RateLimiterUnion');
|
|
10
11
|
const RateLimiterQueue = require('./lib/RateLimiterQueue');
|
|
11
12
|
const BurstyRateLimiter = require('./lib/BurstyRateLimiter');
|
|
@@ -33,6 +34,7 @@ module.exports = {
|
|
|
33
34
|
RateLimiterClusterMasterPM2,
|
|
34
35
|
RateLimiterCluster,
|
|
35
36
|
RLWrapperBlackAndWhite,
|
|
37
|
+
RLWrapperTimeouts,
|
|
36
38
|
RateLimiterUnion,
|
|
37
39
|
RateLimiterQueue,
|
|
38
40
|
BurstyRateLimiter,
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const RateLimiterAbstract = require('./RateLimiterAbstract');
|
|
2
|
+
const RateLimiterInsuredAbstract = require('./RateLimiterInsuredAbstract');
|
|
3
|
+
|
|
4
|
+
module.exports = class RLWrapperTimeouts extends RateLimiterInsuredAbstract {
|
|
5
|
+
constructor(opts= {}) {
|
|
6
|
+
super(opts);
|
|
7
|
+
this.limiter = opts.limiter;
|
|
8
|
+
this.timeoutMs = opts.timeoutMs || 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
get limiter() {
|
|
12
|
+
return this._limiter;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
set limiter(limiter) {
|
|
16
|
+
if (!(limiter instanceof RateLimiterAbstract)) {
|
|
17
|
+
throw new TypeError('limiter must be an instance of RateLimiterAbstract');
|
|
18
|
+
}
|
|
19
|
+
this._limiter = limiter;
|
|
20
|
+
if (!this.insuranceLimiter && limiter instanceof RateLimiterInsuredAbstract) {
|
|
21
|
+
this.insuranceLimiter = limiter.insuranceLimiter;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get timeoutMs() {
|
|
26
|
+
return this._timeoutMs;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
set timeoutMs(value) {
|
|
30
|
+
if (typeof value !== 'number' || value < 0) {
|
|
31
|
+
throw new TypeError('timeoutMs must be a non-negative number');
|
|
32
|
+
}
|
|
33
|
+
this._timeoutMs = value;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
_run(funcName, params) {
|
|
37
|
+
return new Promise(async (resolve, reject) => {
|
|
38
|
+
const timeout = setTimeout(() => {
|
|
39
|
+
return reject(new Error('Operation timed out'));
|
|
40
|
+
}, this.timeoutMs);
|
|
41
|
+
|
|
42
|
+
await this.limiter[funcName](...params)
|
|
43
|
+
.then((result) => {
|
|
44
|
+
clearTimeout(timeout);
|
|
45
|
+
resolve(result);
|
|
46
|
+
})
|
|
47
|
+
.catch((err) => {
|
|
48
|
+
clearTimeout(timeout);
|
|
49
|
+
reject(err);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
_consume(key, pointsToConsume = 1, options = {}) {
|
|
55
|
+
return this._run('consume', [key, pointsToConsume, options]);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
_penalty(key, points = 1, options = {}) {
|
|
59
|
+
return this._run('penalty', [key, points, options]);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
_reward(key, points = 1, options = {}) {
|
|
63
|
+
return this._run('reward', [key, points, options]);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
_get(key, options = {}) {
|
|
67
|
+
return this._run('get', [key, options]);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
_set(key, points, secDuration, options = {}) {
|
|
71
|
+
return this._run('set', [key, points, secDuration, options]);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
_block(key, secDuration, options = {}) {
|
|
75
|
+
return this._run('block', [key, secDuration, options]);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
_delete(key, options = {}) {
|
|
79
|
+
return this._run('delete', [key, options]);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
const RateLimiterAbstract = require('./RateLimiterAbstract');
|
|
2
|
+
const RateLimiterRes = require('./RateLimiterRes');
|
|
3
|
+
|
|
4
|
+
module.exports = class RateLimiterInsuredAbstract extends RateLimiterAbstract {
|
|
5
|
+
constructor(opts = {}) {
|
|
6
|
+
super(opts);
|
|
7
|
+
this.insuranceLimiter = opts.insuranceLimiter;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
get insuranceLimiter() {
|
|
11
|
+
return this._insuranceLimiter;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
set insuranceLimiter(value) {
|
|
15
|
+
if (typeof value !== 'undefined' && !(value instanceof RateLimiterAbstract)) {
|
|
16
|
+
throw new Error('insuranceLimiter must be instance of RateLimiterAbstract');
|
|
17
|
+
}
|
|
18
|
+
this._insuranceLimiter = value;
|
|
19
|
+
if (this._insuranceLimiter) {
|
|
20
|
+
this._insuranceLimiter.blockDuration = this.blockDuration;
|
|
21
|
+
this._insuranceLimiter.execEvenly = this.execEvenly;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
_handleError(err, funcName, resolve, reject, params) {
|
|
26
|
+
if (err instanceof RateLimiterRes) {
|
|
27
|
+
reject(err);
|
|
28
|
+
} else if (!(this.insuranceLimiter instanceof RateLimiterAbstract)) {
|
|
29
|
+
reject(err);
|
|
30
|
+
} else {
|
|
31
|
+
this.insuranceLimiter[funcName](...params)
|
|
32
|
+
.then((res) => {
|
|
33
|
+
resolve(res);
|
|
34
|
+
})
|
|
35
|
+
.catch((res) => {
|
|
36
|
+
reject(res);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
_operation(funcName, params) {
|
|
42
|
+
const promise = this[funcName](...params);
|
|
43
|
+
return new Promise((resolve, reject) => {
|
|
44
|
+
return promise.then((res) => {
|
|
45
|
+
resolve(res);
|
|
46
|
+
})
|
|
47
|
+
.catch((err) => {
|
|
48
|
+
if (funcName.startsWith('_')) {
|
|
49
|
+
funcName = funcName.slice(1);
|
|
50
|
+
}
|
|
51
|
+
this._handleError(err, funcName, resolve, reject, params);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
consume(key, pointsToConsume = 1, options = {}) {
|
|
57
|
+
return this._operation('_consume', [key, pointsToConsume, options]);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
penalty(key, points = 1, options = {}) {
|
|
61
|
+
return this._operation('_penalty', [key, points, options]);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
reward(key, points = 1, options = {}) {
|
|
65
|
+
return this._operation('_reward', [key, points, options]);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get(key, options = {}) {
|
|
69
|
+
return this._operation('_get', [key, options]);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
set(key, points, secDuration, options = {}) {
|
|
73
|
+
return this._operation('_set', [key, points, secDuration, options]);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
block(key, secDuration, options = {}) {
|
|
77
|
+
return this._operation('_block', [key, secDuration, options]);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
delete(key, options = {}) {
|
|
81
|
+
return this._operation('_delete', [key, options]);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
_consume() {
|
|
85
|
+
throw new Error("You have to implement the method '_consume'!");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
_penalty() {
|
|
89
|
+
throw new Error("You have to implement the method '_penalty'!");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
_reward() {
|
|
93
|
+
throw new Error("You have to implement the method '_reward'!");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
_get() {
|
|
97
|
+
throw new Error("You have to implement the method '_get'!");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
_set() {
|
|
101
|
+
throw new Error("You have to implement the method '_set'!");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
_block() {
|
|
105
|
+
throw new Error("You have to implement the method '_block'!");
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
_delete() {
|
|
109
|
+
throw new Error("You have to implement the method '_delete'!");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
}
|
package/lib/RateLimiterMongo.js
CHANGED
|
@@ -1,34 +1,6 @@
|
|
|
1
1
|
const RateLimiterStoreAbstract = require('./RateLimiterStoreAbstract');
|
|
2
2
|
const RateLimiterRes = require('./RateLimiterRes');
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* Get MongoDB driver version as upsert options differ
|
|
6
|
-
* @params {Object} Client instance
|
|
7
|
-
* @returns {Object} Version Object containing major, feature & minor versions.
|
|
8
|
-
*/
|
|
9
|
-
function getDriverVersion(client) {
|
|
10
|
-
try {
|
|
11
|
-
const _client = client.client ? client.client : client;
|
|
12
|
-
|
|
13
|
-
let _v = [0, 0, 0];
|
|
14
|
-
if (typeof _client.topology === 'undefined') {
|
|
15
|
-
const { version } = _client.options.metadata.driver;
|
|
16
|
-
_v = version.split('|', 1)[0].split('.').map(v => parseInt(v));
|
|
17
|
-
} else {
|
|
18
|
-
const { version } = _client.topology.s.options.metadata.driver;
|
|
19
|
-
_v = version.split('.').map(v => parseInt(v));
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return {
|
|
23
|
-
major: _v[0],
|
|
24
|
-
feature: _v[1],
|
|
25
|
-
patch: _v[2],
|
|
26
|
-
};
|
|
27
|
-
} catch (err) {
|
|
28
|
-
return { major: 0, feature: 0, patch: 0 };
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
4
|
class RateLimiterMongo extends RateLimiterStoreAbstract {
|
|
33
5
|
/**
|
|
34
6
|
*
|
|
@@ -59,11 +31,9 @@ class RateLimiterMongo extends RateLimiterStoreAbstract {
|
|
|
59
31
|
.then((conn) => {
|
|
60
32
|
this.client = conn;
|
|
61
33
|
this._initCollection();
|
|
62
|
-
this._driverVersion = getDriverVersion(this.client);
|
|
63
34
|
});
|
|
64
35
|
} else {
|
|
65
36
|
this._initCollection();
|
|
66
|
-
this._driverVersion = getDriverVersion(this.client);
|
|
67
37
|
}
|
|
68
38
|
}
|
|
69
39
|
|
|
@@ -198,20 +168,11 @@ class RateLimiterMongo extends RateLimiterStoreAbstract {
|
|
|
198
168
|
upsertData.$setOnInsert = Object.assign(upsertData.$setOnInsert, docAttrs);
|
|
199
169
|
}
|
|
200
170
|
|
|
201
|
-
//
|
|
171
|
+
// All supported MongoDB drivers (3.6.7+) use returnDocument: 'after'
|
|
202
172
|
const upsertOptions = {
|
|
203
173
|
upsert: true,
|
|
174
|
+
returnDocument: 'after',
|
|
204
175
|
};
|
|
205
|
-
if ((this._driverVersion.major >= 4) ||
|
|
206
|
-
(this._driverVersion.major === 3 &&
|
|
207
|
-
(this._driverVersion.feature >=7) ||
|
|
208
|
-
(this._driverVersion.feature >= 6 &&
|
|
209
|
-
this._driverVersion.patch >= 7 )))
|
|
210
|
-
{
|
|
211
|
-
upsertOptions.returnDocument = 'after';
|
|
212
|
-
} else {
|
|
213
|
-
upsertOptions.returnOriginal = false;
|
|
214
|
-
}
|
|
215
176
|
|
|
216
177
|
/*
|
|
217
178
|
* 1. Find actual limit and increment points
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
const RateLimiterAbstract = require('./RateLimiterAbstract');
|
|
2
2
|
const BlockedKeys = require('./component/BlockedKeys');
|
|
3
3
|
const RateLimiterRes = require('./RateLimiterRes');
|
|
4
|
+
const RateLimiterInsuredAbstract = require('./RateLimiterInsuredAbstract');
|
|
4
5
|
|
|
5
|
-
module.exports = class RateLimiterStoreAbstract extends
|
|
6
|
+
module.exports = class RateLimiterStoreAbstract extends RateLimiterInsuredAbstract {
|
|
6
7
|
/**
|
|
7
8
|
*
|
|
8
9
|
* @param opts Object Defaults {
|
|
@@ -18,7 +19,6 @@ module.exports = class RateLimiterStoreAbstract extends RateLimiterAbstract {
|
|
|
18
19
|
|
|
19
20
|
this.inMemoryBlockOnConsumed = opts.inMemoryBlockOnConsumed;
|
|
20
21
|
this.inMemoryBlockDuration = opts.inMemoryBlockDuration;
|
|
21
|
-
this.insuranceLimiter = opts.insuranceLimiter;
|
|
22
22
|
this._inMemoryBlockedKeys = new BlockedKeys();
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -92,20 +92,6 @@ module.exports = class RateLimiterStoreAbstract extends RateLimiterAbstract {
|
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
_handleError(err, funcName, resolve, reject, key, data = false, options = {}) {
|
|
96
|
-
if (!(this.insuranceLimiter instanceof RateLimiterAbstract)) {
|
|
97
|
-
reject(err);
|
|
98
|
-
} else {
|
|
99
|
-
this.insuranceLimiter[funcName](key, data, options)
|
|
100
|
-
.then((res) => {
|
|
101
|
-
resolve(res);
|
|
102
|
-
})
|
|
103
|
-
.catch((res) => {
|
|
104
|
-
reject(res);
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
95
|
getInMemoryBlockMsBeforeExpire(rlKey) {
|
|
110
96
|
if (this.inMemoryBlockOnConsumed > 0) {
|
|
111
97
|
return this._inMemoryBlockedKeys.msBeforeExpire(rlKey);
|
|
@@ -140,21 +126,6 @@ module.exports = class RateLimiterStoreAbstract extends RateLimiterAbstract {
|
|
|
140
126
|
return this._inMemoryBlockDuration * 1000;
|
|
141
127
|
}
|
|
142
128
|
|
|
143
|
-
get insuranceLimiter() {
|
|
144
|
-
return this._insuranceLimiter;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
set insuranceLimiter(value) {
|
|
148
|
-
if (typeof value !== 'undefined' && !(value instanceof RateLimiterAbstract)) {
|
|
149
|
-
throw new Error('insuranceLimiter must be instance of RateLimiterAbstract');
|
|
150
|
-
}
|
|
151
|
-
this._insuranceLimiter = value;
|
|
152
|
-
if (this._insuranceLimiter) {
|
|
153
|
-
this._insuranceLimiter.blockDuration = this.blockDuration;
|
|
154
|
-
this._insuranceLimiter.execEvenly = this.execEvenly;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
129
|
/**
|
|
159
130
|
* Block any key for secDuration seconds
|
|
160
131
|
*
|
|
@@ -191,7 +162,7 @@ module.exports = class RateLimiterStoreAbstract extends RateLimiterAbstract {
|
|
|
191
162
|
* @param {Object} options
|
|
192
163
|
* @returns Promise<RateLimiterRes>
|
|
193
164
|
*/
|
|
194
|
-
|
|
165
|
+
_consume(key, pointsToConsume = 1, options = {}) {
|
|
195
166
|
return new Promise((resolve, reject) => {
|
|
196
167
|
const rlKey = this.getKey(key);
|
|
197
168
|
|
|
@@ -204,9 +175,7 @@ module.exports = class RateLimiterStoreAbstract extends RateLimiterAbstract {
|
|
|
204
175
|
.then((res) => {
|
|
205
176
|
this._afterConsume(resolve, reject, rlKey, pointsToConsume, res);
|
|
206
177
|
})
|
|
207
|
-
.catch((err) =>
|
|
208
|
-
this._handleError(err, 'consume', resolve, reject, key, pointsToConsume, options);
|
|
209
|
-
});
|
|
178
|
+
.catch((err) => reject(err));
|
|
210
179
|
});
|
|
211
180
|
}
|
|
212
181
|
|
|
@@ -217,16 +186,14 @@ module.exports = class RateLimiterStoreAbstract extends RateLimiterAbstract {
|
|
|
217
186
|
* @param {Object} options
|
|
218
187
|
* @returns Promise<RateLimiterRes>
|
|
219
188
|
*/
|
|
220
|
-
|
|
189
|
+
_penalty(key, points = 1, options = {}) {
|
|
221
190
|
const rlKey = this.getKey(key);
|
|
222
191
|
return new Promise((resolve, reject) => {
|
|
223
192
|
this._upsert(rlKey, points, this._getKeySecDuration(options) * 1000, false, options)
|
|
224
193
|
.then((res) => {
|
|
225
194
|
resolve(this._getRateLimiterRes(rlKey, points, res));
|
|
226
195
|
})
|
|
227
|
-
.catch((
|
|
228
|
-
this._handleError(err, 'penalty', resolve, reject, key, points, options);
|
|
229
|
-
});
|
|
196
|
+
.catch((res) => reject(res));
|
|
230
197
|
});
|
|
231
198
|
}
|
|
232
199
|
|
|
@@ -237,16 +204,14 @@ module.exports = class RateLimiterStoreAbstract extends RateLimiterAbstract {
|
|
|
237
204
|
* @param {Object} options
|
|
238
205
|
* @returns Promise<RateLimiterRes>
|
|
239
206
|
*/
|
|
240
|
-
|
|
207
|
+
_reward(key, points = 1, options = {}) {
|
|
241
208
|
const rlKey = this.getKey(key);
|
|
242
209
|
return new Promise((resolve, reject) => {
|
|
243
210
|
this._upsert(rlKey, -points, this._getKeySecDuration(options) * 1000, false, options)
|
|
244
211
|
.then((res) => {
|
|
245
212
|
resolve(this._getRateLimiterRes(rlKey, -points, res));
|
|
246
213
|
})
|
|
247
|
-
.catch((
|
|
248
|
-
this._handleError(err, 'reward', resolve, reject, key, points, options);
|
|
249
|
-
});
|
|
214
|
+
.catch((res) => reject(res));
|
|
250
215
|
});
|
|
251
216
|
}
|
|
252
217
|
|
|
@@ -268,7 +233,7 @@ module.exports = class RateLimiterStoreAbstract extends RateLimiterAbstract {
|
|
|
268
233
|
}
|
|
269
234
|
})
|
|
270
235
|
.catch((err) => {
|
|
271
|
-
this._handleError(err, 'get', resolve, reject, key, options);
|
|
236
|
+
this._handleError(err, 'get', resolve, reject, [key, options]);
|
|
272
237
|
});
|
|
273
238
|
});
|
|
274
239
|
}
|
|
@@ -288,7 +253,7 @@ module.exports = class RateLimiterStoreAbstract extends RateLimiterAbstract {
|
|
|
288
253
|
resolve(res);
|
|
289
254
|
})
|
|
290
255
|
.catch((err) => {
|
|
291
|
-
this._handleError(err, 'delete', resolve, reject, key, options);
|
|
256
|
+
this._handleError(err, 'delete', resolve, reject, [key, options]);
|
|
292
257
|
});
|
|
293
258
|
});
|
|
294
259
|
}
|
|
@@ -330,7 +295,7 @@ module.exports = class RateLimiterStoreAbstract extends RateLimiterAbstract {
|
|
|
330
295
|
resolve(new RateLimiterRes(0, msDuration > 0 ? msDuration : -1, initPoints));
|
|
331
296
|
})
|
|
332
297
|
.catch((err) => {
|
|
333
|
-
this._handleError(err, 'block', resolve, reject, this.parseKey(rlKey), msDuration / 1000, options);
|
|
298
|
+
this._handleError(err, 'block', resolve, reject, [this.parseKey(rlKey), msDuration / 1000, options]);
|
|
334
299
|
});
|
|
335
300
|
});
|
|
336
301
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rate-limiter-flexible",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Node.js
|
|
3
|
+
"version": "9.0.0",
|
|
4
|
+
"description": "Node.js atomic and non-atomic counters, rate limiting tools, protection from DoS and brute-force attacks at scale",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"dc:up": "docker-compose -f docker-compose.yml up -d",
|
package/types.d.ts
CHANGED
|
@@ -204,7 +204,11 @@ export class RateLimiterAbstract {
|
|
|
204
204
|
): Promise<boolean>;
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
-
export class
|
|
207
|
+
export class RateLimiterInsuredAbstract extends RateLimiterAbstract {
|
|
208
|
+
constructor(opts: IRateLimiterOptions);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export class RateLimiterStoreAbstract extends RateLimiterInsuredAbstract {
|
|
208
212
|
constructor(opts: IRateLimiterStoreOptions);
|
|
209
213
|
|
|
210
214
|
/**
|
|
@@ -220,6 +224,7 @@ interface IRateLimiterOptions {
|
|
|
220
224
|
execEvenly?: boolean;
|
|
221
225
|
execEvenlyMinDelayMs?: number;
|
|
222
226
|
blockDuration?: number;
|
|
227
|
+
insuranceLimiter?: RateLimiterAbstract;
|
|
223
228
|
}
|
|
224
229
|
|
|
225
230
|
interface IRateLimiterClusterOptions extends IRateLimiterOptions {
|
|
@@ -393,6 +398,15 @@ export class RLWrapperBlackAndWhite extends RateLimiterAbstract {
|
|
|
393
398
|
constructor(opts: IRLWrapperBlackAndWhiteOptions);
|
|
394
399
|
}
|
|
395
400
|
|
|
401
|
+
interface IRLWrapperTimeoutsOptions extends IRateLimiterOptions {
|
|
402
|
+
limiter: RateLimiterAbstract;
|
|
403
|
+
timeoutMs?: number;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
export class RLWrapperTimeouts extends RateLimiterInsuredAbstract {
|
|
407
|
+
constructor(opts: IRLWrapperTimeoutsOptions);
|
|
408
|
+
}
|
|
409
|
+
|
|
396
410
|
interface IRateLimiterQueueOpts {
|
|
397
411
|
maxQueueSize?: number;
|
|
398
412
|
}
|