Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

rate-limiter-flexible

Package Overview
Dependencies
Maintainers
1
Versions
164
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rate-limiter-flexible - npm Package Compare versions

Comparing version 1.1.6 to 1.2.0

29

lib/component/MemoryStorage/MemoryStorage.js

@@ -15,4 +15,6 @@ const Record = require('./Record');

if (this._storage[key]) {
const msBeforeExpires = this._storage[key].expiresAt.getTime() - new Date().getTime();
if (msBeforeExpires > 0) {
const msBeforeExpires = this._storage[key].expiresAt
? this._storage[key].expiresAt.getTime() - new Date().getTime()
: -1;
if (msBeforeExpires !== 0) {
// Change value

@@ -32,13 +34,18 @@ this._storage[key].value = this._storage[key].value + value;

if (this._storage[key]) {
if (this._storage[key] && this._storage[key].timeoutId) {
clearTimeout(this._storage[key].timeoutId);
}
this._storage[key] = new Record(value, new Date(Date.now() + durationMs));
this._storage[key].timeoutId = setTimeout(() => {
delete this._storage[key];
}, durationMs);
this._storage[key].timeoutId.unref();
this._storage[key] = new Record(
value,
durationMs > 0 ? new Date(Date.now() + durationMs) : null
);
if (durationMs > 0) {
this._storage[key].timeoutId = setTimeout(() => {
delete this._storage[key];
}, durationMs);
this._storage[key].timeoutId.unref();
}
return new RateLimiterRes(0, durationMs, this._storage[key].value, true);
return new RateLimiterRes(0, durationMs === 0 ? -1 : durationMs, this._storage[key].value, true);
}

@@ -53,3 +60,5 @@

if (this._storage[key]) {
const msBeforeExpires = this._storage[key].expiresAt.getTime() - new Date().getTime();
const msBeforeExpires = this._storage[key].expiresAt
? this._storage[key].expiresAt.getTime() - new Date().getTime()
: -1;
return new RateLimiterRes(0, msBeforeExpires, this._storage[key].value, false);

@@ -56,0 +65,0 @@ }

@@ -35,3 +35,3 @@ module.exports = class RateLimiterAbstract {

set duration(value) {
this._duration = value || 1;
this._duration = typeof value === 'undefined' ? 1 : value;
}

@@ -38,0 +38,0 @@

@@ -38,9 +38,14 @@ const RateLimiterStoreAbstract = require('./RateLimiterStoreAbstract');

if (!err) {
this.client.set(`${rlKey}_expire`, nowMs + (secDuration * 1000), secDuration, () => {
const res = {
consumedPoints: points,
msBeforeNext: secDuration * 1000,
};
resolve(res);
});
this.client.set(
`${rlKey}_expire`,
secDuration > 0 ? nowMs + (secDuration * 1000) : -1,
secDuration,
() => {
const res = {
consumedPoints: points,
msBeforeNext: secDuration > 0 ? secDuration * 1000 : -1,
};
resolve(res);
}
);
} else {

@@ -67,9 +72,14 @@ reject(err);

} else {
this.client.add(`${rlKey}_expire`, nowMs + (secDuration * 1000), secDuration, () => {
const res = {
consumedPoints: points,
msBeforeNext: secDuration * 1000,
};
resolve(res);
});
this.client.add(
`${rlKey}_expire`,
secDuration > 0 ? nowMs + (secDuration * 1000) : -1,
secDuration,
() => {
const res = {
consumedPoints: points,
msBeforeNext: secDuration > 0 ? secDuration * 1000 : -1,
};
resolve(res);
}
);
}

@@ -82,6 +92,6 @@ });

} else {
const expireMs = !resGetExpireMs ? 0 : resGetExpireMs;
const expireMs = resGetExpireMs === false ? 0 : resGetExpireMs;
const res = {
consumedPoints,
msBeforeNext: Math.max(expireMs - nowMs, 0),
msBeforeNext: expireMs >= 0 ? Math.max(expireMs - nowMs, 0) : -1,
};

@@ -109,6 +119,6 @@ resolve(res);

} else {
const expireMs = !resGetExpireMs ? 0 : resGetExpireMs;
const expireMs = resGetExpireMs === false ? 0 : resGetExpireMs;
const res = {
consumedPoints,
msBeforeNext: Math.max(expireMs - nowMs, 0),
msBeforeNext: expireMs >= 0 ? Math.max(expireMs - nowMs, 0) : -1,
};

@@ -115,0 +125,0 @@ resolve(res);

@@ -108,3 +108,5 @@ const RateLimiterStoreAbstract = require('./RateLimiterStoreAbstract');

res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
res.msBeforeNext = Math.max(new Date(doc.expire).getTime() - Date.now(), 0);
res.msBeforeNext = doc.expire !== null
? Math.max(new Date(doc.expire).getTime() - Date.now(), 0)
: -1;

@@ -130,3 +132,3 @@ return res;

points,
expire: new Date(Date.now() + msDuration),
expire: msDuration > 0 ? new Date(Date.now() + msDuration) : null,
},

@@ -137,3 +139,6 @@ };

where = {
expire: { $gt: new Date() },
$or: [
{ expire: { $gt: new Date() } },
{ expire: { $eq: null } },
],
key,

@@ -145,3 +150,3 @@ };

key,
expire: new Date(Date.now() + msDuration),
expire: msDuration > 0 ? new Date(Date.now() + msDuration) : null,
},

@@ -171,4 +176,7 @@ $inc: { points },

if (errUpsert && errUpsert.code === 11000) { // E11000 duplicate key error collection
const replaceWhere = Object.assign({
expire: { $lte: new Date() }, // try to replace OLD limit doc
const replaceWhere = Object.assign({ // try to replace OLD limit doc
$or: [
{ expire: { $lte: new Date() } },
{ expire: { $eq: null } },
],
key,

@@ -180,3 +188,3 @@ }, docAttrs);

points,
expire: new Date(Date.now() + msDuration),
expire: msDuration > 0 ? new Date(Date.now() + msDuration) : null,
}, docAttrs);

@@ -218,3 +226,6 @@

key: rlKey,
expire: { $gt: new Date() },
$or: [
{ expire: { $gt: new Date() } },
{ expire: { $eq: null } },
],
}, docAttrs);

@@ -221,0 +232,0 @@

@@ -152,3 +152,3 @@ const RateLimiterStoreAbstract = require('./RateLimiterStoreAbstract');

'`points` INT(9) NOT NULL default 0,' +
'`expire` BIGINT UNSIGNED NOT NULL,' +
'`expire` BIGINT UNSIGNED,' +
'PRIMARY KEY (`key`)' +

@@ -209,3 +209,5 @@ ') ENGINE = INNODB;';

res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
res.msBeforeNext = Math.max(row.expire - Date.now(), 0);
res.msBeforeNext = row.expire
? Math.max(row.expire - Date.now(), 0)
: -1;

@@ -225,3 +227,3 @@ return res;

const dateNow = Date.now();
const newExpire = dateNow + msDuration;
const newExpire = msDuration > 0 ? dateNow + msDuration : null;

@@ -313,3 +315,3 @@ let q;

conn.query(
'SELECT points, expire FROM ??.?? WHERE `key` = ? AND `expire` > ?',
'SELECT points, expire FROM ??.?? WHERE `key` = ? AND (`expire` > ? OR `expire` IS NULL)',
[this.dbName, this.tableName, rlKey, Date.now()],

@@ -316,0 +318,0 @@ (err, res) => {

@@ -146,3 +146,3 @@ const RateLimiterStoreAbstract = require('./RateLimiterStoreAbstract');

points integer NOT NULL DEFAULT 0,
expire bigint NOT NULL
expire bigint
);`;

@@ -194,3 +194,5 @@ }

res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
res.msBeforeNext = Math.max(row.expire - Date.now(), 0);
res.msBeforeNext = row.expire
? Math.max(row.expire - Date.now(), 0)
: -1;

@@ -227,3 +229,3 @@ return res;

const newExpire = Date.now() + msDuration;
const newExpire = msDuration > 0 ? Date.now() + msDuration : null;
const expireQ = forceExpire

@@ -260,3 +262,3 @@ ? ' $3 '

text: `
SELECT points, expire FROM ${this.tableName} WHERE key = $1 AND expire > $2;`,
SELECT points, expire FROM ${this.tableName} WHERE key = $1 AND (expire > $2 OR expire IS NULL);`,
values: [rlKey, Date.now()],

@@ -263,0 +265,0 @@ })

@@ -24,9 +24,25 @@ const RateLimiterStoreAbstract = require('./RateLimiterStoreAbstract');

_getRateLimiterRes(rlKey, changedPoints, result) {
let [resSet, consumed, resTtlMs] = result;
// Support ioredis results format
if (Array.isArray(resSet)) {
[, resSet] = resSet;
[, consumed] = consumed;
[, resTtlMs] = resTtlMs;
let resSet, consumed, resTtlMs, secDuration
let isKeyNeverExpired = false
if (result.length === 2) {
[consumed, resTtlMs] = result
// Support ioredis results format
if (Array.isArray(consumed)) {
[, consumed] = consumed;
[, resTtlMs] = resTtlMs;
}
isKeyNeverExpired = true
} else {
[resSet, consumed, resTtlMs, secDuration] = result
// Support ioredis results format
if (Array.isArray(resSet)) {
[, resSet] = resSet;
[, consumed] = consumed;
[, resTtlMs] = resTtlMs;
}
if (resSet === 'FORCE' && secDuration === 0) {
isKeyNeverExpired = true
}
}
const res = new RateLimiterRes();

@@ -36,4 +52,5 @@ res.consumedPoints = parseInt(consumed);

res.remainingPoints = Math.max(this.points - res.consumedPoints, 0);
if (resTtlMs === -1) {
// If rlKey created by incrby() not by set()
// TODO: Fix Redis race conditions on transaction level with proper Lua script
if (resTtlMs === -1 && !isKeyNeverExpired && resSet !== 'GET') {
// If rlKey created by incrby() not by set(), this happens really rare
res.isFirstInDuration = true;

@@ -52,7 +69,11 @@ res.msBeforeNext = this.duration;

const secDuration = Math.floor(msDuration / 1000);
const multi = this.client.multi();
if (forceExpire) {
this.client
.multi()
.set(rlKey, points, 'EX', secDuration)
.pttl(rlKey)
if (secDuration > 0) {
multi.set(rlKey, points, 'EX', secDuration);
} else {
multi.set(rlKey, points);
}
multi.pttl(rlKey)
.exec((err, res) => {

@@ -63,9 +84,10 @@ if (err) {

return resolve(['FORCE', points, res[1]]);
return resolve(['FORCE', points, res[1], secDuration]);
});
} else {
this.client
.multi()
.set(rlKey, 0, 'EX', secDuration, 'NX')
.incrby(rlKey, points)
if (secDuration > 0) {
multi.set(rlKey, 0, 'EX', secDuration, 'NX');
}
multi.incrby(rlKey, points)
.pttl(rlKey)

@@ -72,0 +94,0 @@ .exec((err, res) => {

@@ -298,3 +298,3 @@ const RateLimiterAbstract = require('./RateLimiterAbstract');

.then(() => {
resolve(new RateLimiterRes(0, msDuration, initPoints));
resolve(new RateLimiterRes(0, msDuration > 0 ? msDuration : -1, initPoints));
})

@@ -301,0 +301,0 @@ .catch((err) => {

{
"name": "rate-limiter-flexible",
"version": "1.1.6",
"version": "1.2.0",
"description": "Node.js rate limiter by key and protection from DDoS and Brute-Force attacks in process Memory, Redis, MongoDb, Memcached, MySQL, PostgreSQL, Cluster or PM",

@@ -5,0 +5,0 @@ "main": "index.js",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc