Socket
Socket
Sign inDemoInstall

rate-limiter-flexible

Package Overview
Dependencies
0
Maintainers
1
Versions
163
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.6.1 to 0.7.0

.eslintrc.json

6

lib/component/BlockedKeys/BlockedKeys.js

@@ -10,7 +10,7 @@ module.exports = class BlockedKeys {

for(let key in this._keys) {
Object.keys(this._keys).forEach((key) => {
if (this._keys[key] <= now) {
delete this._keys[key];
}
}
});

@@ -27,3 +27,3 @@ this._addedKeysAmount = Object.keys(this._keys).length;

add(key, sec) {
this._keys[key] = Date.now() + sec * 1000;
this._keys[key] = Date.now() + (sec * 1000);
this._addedKeysAmount++;

@@ -30,0 +30,0 @@ if (this._addedKeysAmount > 999) {

@@ -1,7 +0,8 @@

const expect = require('chai').expect;
const { describe, it, beforeEach } = require('mocha');
const { expect } = require('chai');
const BlockedKeys = require('./BlockedKeys');
describe('BlockedKeys', function() {
describe('BlockedKeys', () => {
let blockedKeys;
beforeEach(function() {
beforeEach(() => {
blockedKeys = new BlockedKeys();

@@ -40,3 +41,3 @@ });

it('collect expired on add if there more than 999 blocked keys', (done) => {
for(let i = 0; i < 1000 ; i++) {
for (let i = 0; i < 1000; i++) {
blockedKeys.add(`key${i}`, 1);

@@ -47,3 +48,4 @@ }

blockedKeys.add('key1', 1);
expect(Object.keys(blockedKeys._keys).length === 1 && blockedKeys._addedKeysAmount === 1).to.equal(true);
expect(Object.keys(blockedKeys._keys).length === 1 && blockedKeys._addedKeysAmount === 1)
.to.equal(true);
done();

@@ -57,3 +59,4 @@ }, 1001);

blockedKeys.msBeforeExpire('key');
expect(Object.keys(blockedKeys._keys).length === 1 && blockedKeys._addedKeysAmount === 1).to.equal(true);
expect(Object.keys(blockedKeys._keys).length === 1 && blockedKeys._addedKeysAmount === 1)
.to.equal(true);
done();

@@ -60,0 +63,0 @@ }, 1001);

const BlockedKeys = require('./BlockedKeys');
module.exports = BlockedKeys;
module.exports = BlockedKeys;
const MemoryStorage = require('./MemoryStorage');
module.exports = MemoryStorage;
module.exports = MemoryStorage;

@@ -20,10 +20,8 @@ const Record = require('./Record');

return new Res(this._storage[key].value, msBeforeExpires);
} else {
clearTimeout(this._storage[key].timeoutId);
}
clearTimeout(this._storage[key].timeoutId);
return this.set(key, value, durationSec);
}
} else {
return this.set(key, value, durationSec);
}
return this.set(key, value, durationSec);
}

@@ -40,3 +38,3 @@

return new Res(value, durationMs);
};
}

@@ -52,6 +50,5 @@ /**

return new Res(this._storage[key].value, msBeforeExpires);
} else {
return null;
}
return null;
}
};
};

@@ -1,5 +0,6 @@

const expect = require('chai').expect;
const { describe, it, beforeEach } = require('mocha');
const { expect } = require('chai');
const MemoryStorage = require('./MemoryStorage');
describe('MemoryStorage', function() {
describe('MemoryStorage', function () {
const testKey = 'test';

@@ -41,3 +42,2 @@ const val = 34;

});
});
});

@@ -40,2 +40,2 @@ module.exports = class Record {

}
};
};

@@ -1,2 +0,3 @@

const expect = require('chai').expect;
const { describe, it, beforeEach } = require('mocha');
const { expect } = require('chai');
const Record = require('./Record');

@@ -6,3 +7,3 @@

let record;
beforeEach(function() {
beforeEach(() => {
record = new Record();

@@ -9,0 +10,0 @@ });

@@ -22,2 +22,2 @@ module.exports = class Res {

}
};
};

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

if (typeof value !== 'string') {
throw new Error("keyPrefix must be string");
throw new Error('keyPrefix must be string');
}

@@ -58,3 +58,3 @@ this._keyPrefix = value;

getKey(key) {
return this.keyPrefix + ':' + key;
return `${this.keyPrefix}:${key}`;
}

@@ -61,0 +61,0 @@

@@ -26,10 +26,8 @@ const RateLimiterAbstract = require('./RateLimiterAbstract');

reject(new RateLimiterRes(0, storageRes.msBeforeNext));
} else if (this.execEvenly && storageRes.msBeforeNext > 0 && !isFirstInDuration) {
const delay = Math.ceil(storageRes.msBeforeNext / ((this.points - storageRes.consumedPoints) + 2));
setTimeout(resolve, delay, res);
} else {
if (this.execEvenly && storageRes.msBeforeNext > 0 && !isFirstInDuration) {
const delay = Math.ceil(storageRes.msBeforeNext / ((this.points - storageRes.consumedPoints) + 2));
setTimeout(resolve, delay, res);
} else {
resolve(res);
}
resolve(res);
}

@@ -41,3 +39,3 @@ });

const rlKey = this.getKey(key);
return new Promise((resolve, reject) => {
return new Promise((resolve) => {
const res = this._memoryStorage.incrby(rlKey, points, this.duration);

@@ -50,3 +48,3 @@ resolve(new RateLimiterRes(this.points - res.consumedPoints, res.msBeforeNext));

const rlKey = this.getKey(key);
return new Promise((resolve, reject) => {
return new Promise((resolve) => {
const res = this._memoryStorage.incrby(rlKey, -points, this.duration);

@@ -53,0 +51,0 @@ resolve(new RateLimiterRes(this.points - res.consumedPoints, res.msBeforeNext));

@@ -1,5 +0,6 @@

const expect = require('chai').expect;
const { describe, it } = require('mocha');
const { expect } = require('chai');
const RateLimiterMemory = require('./RateLimiterMemory');
describe('RateLimiterMemory with fixed window', function() {
describe('RateLimiterMemory with fixed window', function () {
this.timeout(5000);

@@ -9,3 +10,3 @@

const testKey = 'consume1';
const rateLimiterMemory = new RateLimiterMemory({points: 2, duration: 5});
const rateLimiterMemory = new RateLimiterMemory({ points: 2, duration: 5 });
rateLimiterMemory.consume(testKey)

@@ -24,3 +25,3 @@ .then(() => {

const testKey = 'consume2';
const rateLimiterMemory = new RateLimiterMemory({points: 1, duration: 5});
const rateLimiterMemory = new RateLimiterMemory({ points: 1, duration: 5 });
rateLimiterMemory.consume(testKey, 2)

@@ -39,3 +40,3 @@ .then(() => {})

const testKey = 'consumeEvenly';
const rateLimiterMemory = new RateLimiterMemory({points: 2, duration: 5, execEvenly: true});
const rateLimiterMemory = new RateLimiterMemory({ points: 2, duration: 5, execEvenly: true });
rateLimiterMemory.consume(testKey)

@@ -67,3 +68,3 @@ .then(() => {

const testKey = 'penalty1';
const rateLimiterMemory = new RateLimiterMemory({points: 3, duration: 5});
const rateLimiterMemory = new RateLimiterMemory({ points: 3, duration: 5 });
rateLimiterMemory.consume(testKey)

@@ -88,3 +89,3 @@ .then(() => {

const testKey = 'reward1';
const rateLimiterMemory = new RateLimiterMemory({points: 1, duration: 5});
const rateLimiterMemory = new RateLimiterMemory({ points: 1, duration: 5 });
rateLimiterMemory.consume(testKey)

@@ -110,6 +111,6 @@ .then(() => {

const keyPrefix = 'test';
const rateLimiterMemory = new RateLimiterMemory({keyPrefix: keyPrefix, points: 1, duration: 5});
const rateLimiterMemory = new RateLimiterMemory({ keyPrefix, points: 1, duration: 5 });
expect(rateLimiterMemory.getKey(testKey)).to.equal('test:key');
});
});
});

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

const handleRedisError = function(funcName, resolve, reject, key, pointsToConsume) {
const handleRedisError = function (funcName, resolve, reject, key, pointsToConsume) {
if (!(this.insuranceLimiter instanceof RateLimiterAbstract)) {

@@ -16,7 +16,7 @@ reject(new Error('Redis Client error'));

reject(res);
})
});
}
};
const afterConsume = function(resolve, reject, rlKey, results) {
const afterConsume = function (resolve, reject, rlKey, results) {
const [resSet, consumed, resTtlMs] = results;

@@ -43,9 +43,7 @@ const res = new RateLimiterRes();

reject(res);
} else if (this.execEvenly && res.msBeforeNext > 0 && !isFirstInDuration) {
const delay = Math.ceil(res.msBeforeNext / (res.remainingPoints + 2));
setTimeout(resolve, delay, res);
} else {
if (this.execEvenly && res.msBeforeNext > 0 && !isFirstInDuration) {
const delay = Math.ceil(res.msBeforeNext / (res.remainingPoints + 2));
setTimeout(resolve, delay, res);
} else {
resolve(res);
}
resolve(res);
}

@@ -52,0 +50,0 @@ };

@@ -1,6 +0,7 @@

const expect = require('chai').expect;
const { describe, it, beforeEach } = require('mocha');
const { expect } = require('chai');
const RateLimiterRedis = require('./RateLimiterRedis');
const redisMock = require('redis-mock');
describe('RateLimiterRedis with fixed window', function() {
describe('RateLimiterRedis with fixed window', function () {
this.timeout(5000);

@@ -14,8 +15,8 @@ const redisMockClient = redisMock.createClient();

multi.exec = (cb) => {
cb(new Error('closed'), [])
}
cb(new Error('closed'), []);
};
return multi;
}
};
}

@@ -26,11 +27,10 @@ const redisClientClosedRaw = new RedisClient();

get: (func, name) => {
if( name in redisClientClosedRaw ) {
if (name in redisClientClosedRaw) {
return redisClientClosedRaw[name];
}
return function() {
const args = [].slice.call(arguments);
return function (...args) {
const cb = args.pop();
cb(Error('closed'));
}
}
};
},
});

@@ -44,3 +44,3 @@

const testKey = 'consume1';
const rateLimiter = new RateLimiterRedis({redis: redisMockClient, points: 2, duration: 5});
const rateLimiter = new RateLimiterRedis({ redis: redisMockClient, points: 2, duration: 5 });
rateLimiter.consume(testKey)

@@ -53,3 +53,3 @@ .then(() => {

}
})
});
})

@@ -63,3 +63,3 @@ .catch((err) => {

const testKey = 'consume2';
const rateLimiter = new RateLimiterRedis({redis: redisMockClient, points: 1, duration: 5});
const rateLimiter = new RateLimiterRedis({ redis: redisMockClient, points: 1, duration: 5 });
rateLimiter.consume(testKey, 2)

@@ -70,3 +70,3 @@ .then(() => {})

done();
})
});
});

@@ -76,3 +76,5 @@

const testKey = 'consumeEvenly';
const rateLimiter = new RateLimiterRedis({redis: redisMockClient, points: 2, duration: 5, execEvenly: true});
const rateLimiter = new RateLimiterRedis({
redis: redisMockClient, points: 2, duration: 5, execEvenly: true,
});
rateLimiter.consume(testKey)

@@ -104,3 +106,3 @@ .then(() => {

const testKey = 'penalty1';
const rateLimiter = new RateLimiterRedis({redis: redisMockClient, points: 3, duration: 5});
const rateLimiter = new RateLimiterRedis({ redis: redisMockClient, points: 3, duration: 5 });
rateLimiter.consume(testKey)

@@ -115,3 +117,3 @@ .then(() => {

}
})
});
})

@@ -129,3 +131,3 @@ .catch((err) => {

const testKey = 'reward';
const rateLimiter = new RateLimiterRedis({redis: redisMockClient, points: 1, duration: 5});
const rateLimiter = new RateLimiterRedis({ redis: redisMockClient, points: 1, duration: 5 });
rateLimiter.consume(testKey)

@@ -140,3 +142,3 @@ .then(() => {

}
})
});
})

@@ -159,3 +161,3 @@ .catch((err) => {

blockOnPointsConsumed: 2,
blockDuration: 10
blockDuration: 10,
});

@@ -192,3 +194,3 @@ rateLimiter.consume(testKey)

})
.catch((rejRes) => {
.catch(() => {
setTimeout(() => {

@@ -214,2 +216,3 @@ rateLimiter.consume(testKey)

});
rateLimiter.reward('test');
} catch (err) {

@@ -228,2 +231,3 @@ expect(err instanceof Error).to.equal(true);

});
rateLimiter.reward('test');
} catch (err) {

@@ -238,3 +242,2 @@ expect(err instanceof Error).to.equal(true);

const redisClientClosed = new RedisClient();
const rateLimiter = new RateLimiterRedis({

@@ -257,3 +260,2 @@ redis: redisClientClosed,

const redisClientClosed = new RedisClient();
const rateLimiter = new RateLimiterRedis({

@@ -266,4 +268,4 @@ redis: redisClientClosed,

duration: 2,
redis: redisMockClient
})
redis: redisMockClient,
}),
});

@@ -277,3 +279,3 @@

})
.catch((rejRes) => {done(rejRes)});
.catch((rejRes) => { done(rejRes); });
});

@@ -291,8 +293,8 @@

duration: 2,
redis: redisMockClient
})
redis: redisMockClient,
}),
});
rateLimiter.penalty(testKey)
.then((res) => {
.then(() => {
redisMockClient.get(rateLimiter.getKey(testKey), (err, consumedPoints) => {

@@ -303,5 +305,5 @@ if (!err) {

}
})
});
})
.catch((rejRes) => {done(rejRes)});
.catch((rejRes) => { done(rejRes); });
});

@@ -319,10 +321,10 @@

duration: 2,
redis: redisMockClient
})
redis: redisMockClient,
}),
});
rateLimiter.consume(testKey, 2)
.then((res) => {
.then(() => {
rateLimiter.reward(testKey)
.then((res) => {
.then(() => {
redisMockClient.get(rateLimiter.getKey(testKey), (err, consumedPoints) => {

@@ -333,7 +335,7 @@ if (!err) {

}
})
});
})
.catch((rejRes) => {done(rejRes)});
.catch((rejRes) => { done(rejRes); });
})
.catch((rejRes) => {done(rejRes)});
.catch((rejRes) => { done(rejRes); });
});

@@ -344,7 +346,6 @@

const keyPrefix = 'test';
const rateLimiter = new RateLimiterRedis({keyPrefix: keyPrefix, redis: redisClientClosed});
const rateLimiter = new RateLimiterRedis({ keyPrefix, redis: redisClientClosed });
expect(rateLimiter.getKey(testKey)).to.equal('test:key');
});
});
});
module.exports = class RateLimiterRes {
constructor(remainingPoints, msBeforeNext) {
this.remainingPoints = typeof remainingPoints === 'undefined' ? 0 : remainingPoints ; // Remaining points in current duration
this.msBeforeNext = typeof msBeforeNext === 'undefined' ? 0 : msBeforeNext ; // Milliseconds before next action
this.remainingPoints = typeof remainingPoints === 'undefined' ? 0 : remainingPoints; // Remaining points in current duration
this.msBeforeNext = typeof msBeforeNext === 'undefined' ? 0 : msBeforeNext; // Milliseconds before next action
}

@@ -6,0 +6,0 @@

@@ -1,2 +0,3 @@

const expect = require('chai').expect;
const { describe, it, beforeEach } = require('mocha');
const { expect } = require('chai');
const RateLimiterRes = require('./RateLimiterRes');

@@ -6,3 +7,3 @@

let rateLimiterRes;
beforeEach(function() {
beforeEach(() => {
rateLimiterRes = new RateLimiterRes();

@@ -12,3 +13,4 @@ });

it('setup defaults on construct', () => {
expect(rateLimiterRes.msBeforeNext === 0 && rateLimiterRes.remainingPoints === 0).to.be.true;
expect(rateLimiterRes.msBeforeNext === 0 && rateLimiterRes.remainingPoints === 0)
.to.be.equal(true);
});

@@ -15,0 +17,0 @@

{
"name": "rate-limiter-flexible",
"version": "0.6.1",
"version": "0.7.0",
"description": "Flexible API rate limiter backed by Redis for distributed node.js applications",

@@ -9,3 +9,5 @@ "main": "index.js",

"debug-test": "mocha --inspect-brk lib/**/**.test.js",
"coveralls": "cat ./coverage/lcov.info | node node_modules/.bin/coveralls"
"coveralls": "cat ./coverage/lcov.info | node node_modules/.bin/coveralls",
"eslint": "node_modules/eslint/bin/eslint.js --quiet lib/*",
"eslint-fix": "node_modules/eslint/bin/eslint.js --fix lib/*"
},

@@ -35,2 +37,7 @@ "repository": {

"coveralls": "^3.0.1",
"eslint": "^4.19.1",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-node": "^6.0.1",
"eslint-plugin-security": "^1.4.0",
"istanbul": "^0.4.5",

@@ -37,0 +44,0 @@ "mocha": "^5.1.1",

@@ -216,1 +216,9 @@ [![Build Status](https://travis-ci.org/animir/node-rate-limiter-flexible.png)](https://travis-ci.org/animir/node-rate-limiter-flexible)

Returns Promise, where result is consumed points in current duration
## Contribution
Make sure you've launched `npm run eslint`, before creating PR.
You can try to run `npm run eslint-fix` to fix some issues.
Appreciated, feel free!

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc