From df13398d3c70e05c0437dc8a9cfe7e42fe813d6c Mon Sep 17 00:00:00 2001 From: roggervalf Date: Sat, 1 Jun 2024 20:37:12 -0500 Subject: [PATCH 1/4] fix(redis): throw error when passing points as non integer number --- lib/RateLimiterStoreAbstract.js | 4 ++++ test/RateLimiterRedis.ioredis.test.js | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/lib/RateLimiterStoreAbstract.js b/lib/RateLimiterStoreAbstract.js index 8a2cd48..30992d8 100644 --- a/lib/RateLimiterStoreAbstract.js +++ b/lib/RateLimiterStoreAbstract.js @@ -192,6 +192,10 @@ module.exports = class RateLimiterStoreAbstract extends RateLimiterAbstract { * @returns Promise */ consume(key, pointsToConsume = 1, options = {}) { + if(!Number.isInteger(pointsToConsume)){ + throw new Error("Consuming decimal number of points is not supported by this package"); + } + return new Promise((resolve, reject) => { const rlKey = this.getKey(key); diff --git a/test/RateLimiterRedis.ioredis.test.js b/test/RateLimiterRedis.ioredis.test.js index 44d0e87..645108e 100644 --- a/test/RateLimiterRedis.ioredis.test.js +++ b/test/RateLimiterRedis.ioredis.test.js @@ -153,6 +153,24 @@ describe('RateLimiterRedis with fixed window', function RateLimiterRedisTest() { }); }); + describe('when points are passed as decimal numbers', () => { + it('thows error', (done) => { + const testKey = 'consume2'; + const rateLimiter = new RateLimiterRedis({ + storeClient: redisMockClient, + points: 1, + duration: 5 + }); + try { + rateLimiter + .consume(testKey, 1.1) + } catch (error) { + expect(error.message).to.equal('Consuming decimal number of points is not supported by this package'); + done(); + } + }); + }); + it('execute evenly over duration', (done) => { const testKey = 'consumeEvenly'; const rateLimiter = new RateLimiterRedis({ From 16385876098c2edc01fb630ea4a8a6d2e462ccf7 Mon Sep 17 00:00:00 2001 From: roggervalf Date: Sat, 28 Sep 2024 15:04:45 -0500 Subject: [PATCH 2/4] add extra validations for string values --- lib/RateLimiterStoreAbstract.js | 14 +++++-- test/RateLimiterRedis.ioredis.test.js | 59 +++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/lib/RateLimiterStoreAbstract.js b/lib/RateLimiterStoreAbstract.js index 30992d8..94f882a 100644 --- a/lib/RateLimiterStoreAbstract.js +++ b/lib/RateLimiterStoreAbstract.js @@ -192,11 +192,17 @@ module.exports = class RateLimiterStoreAbstract extends RateLimiterAbstract { * @returns Promise */ consume(key, pointsToConsume = 1, options = {}) { - if(!Number.isInteger(pointsToConsume)){ - throw new Error("Consuming decimal number of points is not supported by this package"); - } + return new Promise((resolve, reject) => { + if( + typeof pointsToConsume == 'string' + ){ + if(!RegExp("^[1-9][0-9]*$").test(pointsToConsume)){ + reject(new Error("Consuming string different than integer values is not supported by this package")); + } + } else if (!Number.isInteger(pointsToConsume)){ + reject(new Error("Consuming decimal number of points is not supported by this package")); + } - return new Promise((resolve, reject) => { const rlKey = this.getKey(key); const inMemoryBlockMsBeforeExpire = this.getInMemoryBlockMsBeforeExpire(rlKey); diff --git a/test/RateLimiterRedis.ioredis.test.js b/test/RateLimiterRedis.ioredis.test.js index 645108e..0ff8b2c 100644 --- a/test/RateLimiterRedis.ioredis.test.js +++ b/test/RateLimiterRedis.ioredis.test.js @@ -171,6 +171,65 @@ describe('RateLimiterRedis with fixed window', function RateLimiterRedisTest() { }); }); + it('consume 2 point passed as float', (done) => { + const testKey = 'consume1'; + const rateLimiter = new RateLimiterRedis({ + storeClient: redisMockClient, + points: 3, + duration: 5, + }); + rateLimiter + .consume(testKey, 2.0) + .then(() => { + redisMockClient.get(rateLimiter.getKey(testKey)).then((consumedPoints)=>{ + expect(consumedPoints).to.equal('2'); + done(); + }); + }) + .catch((err) => { + done(err); + }); + }); + + it('consume 2.0 point passed as string', (done) => { + const testKey = 'consume1'; + const rateLimiter = new RateLimiterRedis({ + storeClient: redisMockClient, + points: 3, + duration: 5, + }); + rateLimiter + .consume(testKey, "2.0") + .then(() => { + done(new Error('must not')); + }) + .catch((err) => { + console.log(err.message) + expect(err.message).to.equal('Consuming string different than integer values is not supported by this package') + done(); + }); + }); + + it('consume 2 point passed as string', (done) => { + const testKey = 'consume1'; + const rateLimiter = new RateLimiterRedis({ + storeClient: redisMockClient, + points: 3, + duration: 5, + }); + rateLimiter + .consume(testKey, "2") + .then(() => { + redisMockClient.get(rateLimiter.getKey(testKey)).then((consumedPoints)=>{ + expect(consumedPoints).to.equal('2'); + done(); + }); + }) + .catch((err) => { + done(err); + }); + }); + it('execute evenly over duration', (done) => { const testKey = 'consumeEvenly'; const rateLimiter = new RateLimiterRedis({ From bcae315c95518968b8c38185f6521f4b3c56f2d3 Mon Sep 17 00:00:00 2001 From: roggervalf Date: Sat, 28 Sep 2024 15:11:41 -0500 Subject: [PATCH 3/4] add describe statements --- test/RateLimiterRedis.ioredis.test.js | 105 ++++++++++++++------------ 1 file changed, 55 insertions(+), 50 deletions(-) diff --git a/test/RateLimiterRedis.ioredis.test.js b/test/RateLimiterRedis.ioredis.test.js index 0ff8b2c..a4d2195 100644 --- a/test/RateLimiterRedis.ioredis.test.js +++ b/test/RateLimiterRedis.ioredis.test.js @@ -171,63 +171,68 @@ describe('RateLimiterRedis with fixed window', function RateLimiterRedisTest() { }); }); - it('consume 2 point passed as float', (done) => { - const testKey = 'consume1'; - const rateLimiter = new RateLimiterRedis({ - storeClient: redisMockClient, - points: 3, - duration: 5, - }); - rateLimiter - .consume(testKey, 2.0) - .then(() => { - redisMockClient.get(rateLimiter.getKey(testKey)).then((consumedPoints)=>{ - expect(consumedPoints).to.equal('2'); - done(); - }); - }) - .catch((err) => { - done(err); + describe('when passing points as float without decimal values', () => { + it('does not throw an error', (done) => { + const testKey = 'consume1'; + const rateLimiter = new RateLimiterRedis({ + storeClient: redisMockClient, + points: 3, + duration: 5, }); - }); - - it('consume 2.0 point passed as string', (done) => { - const testKey = 'consume1'; - const rateLimiter = new RateLimiterRedis({ - storeClient: redisMockClient, - points: 3, - duration: 5, + rateLimiter + .consume(testKey, 2.0) + .then(() => { + redisMockClient.get(rateLimiter.getKey(testKey)).then((consumedPoints)=>{ + expect(consumedPoints).to.equal('2'); + done(); + }); + }) + .catch((err) => { + done(err); + }); }); - rateLimiter - .consume(testKey, "2.0") - .then(() => { - done(new Error('must not')); - }) - .catch((err) => { - console.log(err.message) - expect(err.message).to.equal('Consuming string different than integer values is not supported by this package') - done(); - }); }); - it('consume 2 point passed as string', (done) => { - const testKey = 'consume1'; - const rateLimiter = new RateLimiterRedis({ - storeClient: redisMockClient, - points: 3, - duration: 5, - }); - rateLimiter - .consume(testKey, "2") - .then(() => { - redisMockClient.get(rateLimiter.getKey(testKey)).then((consumedPoints)=>{ - expect(consumedPoints).to.equal('2'); + describe('when passing points as string with decimal values', () => { + it('throws error', (done) => { + const testKey = 'consume1'; + const rateLimiter = new RateLimiterRedis({ + storeClient: redisMockClient, + points: 3, + duration: 5, + }); + rateLimiter + .consume(testKey, "2.0") + .then(() => { + done(new Error('must not')); + }) + .catch((err) => { + expect(err.message).to.equal('Consuming string different than integer values is not supported by this package') done(); }); - }) - .catch((err) => { - done(err); + }); + }); + + describe('when passing points as string without decimal values', () => { + it('does not throw an error', (done) => { + const testKey = 'consume1'; + const rateLimiter = new RateLimiterRedis({ + storeClient: redisMockClient, + points: 3, + duration: 5, }); + rateLimiter + .consume(testKey, "2") + .then(() => { + redisMockClient.get(rateLimiter.getKey(testKey)).then((consumedPoints)=>{ + expect(consumedPoints).to.equal('2'); + done(); + }); + }) + .catch((err) => { + done(err); + }); + }); }); it('execute evenly over duration', (done) => { From 86673d23f476b0e94e32ceb94edea8a831c73da0 Mon Sep 17 00:00:00 2001 From: roggervalf Date: Sat, 9 Nov 2024 21:32:43 -0500 Subject: [PATCH 4/4] test: fix test case --- test/RateLimiterRedis.ioredis.test.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/test/RateLimiterRedis.ioredis.test.js b/test/RateLimiterRedis.ioredis.test.js index a4d2195..96e0ab8 100644 --- a/test/RateLimiterRedis.ioredis.test.js +++ b/test/RateLimiterRedis.ioredis.test.js @@ -161,13 +161,16 @@ describe('RateLimiterRedis with fixed window', function RateLimiterRedisTest() { points: 1, duration: 5 }); - try { - rateLimiter + + rateLimiter .consume(testKey, 1.1) - } catch (error) { - expect(error.message).to.equal('Consuming decimal number of points is not supported by this package'); - done(); - } + .then(() => { + done(new Error('must not')); + }) + .catch((err) => { + expect(err.message).to.equal('Consuming decimal number of points is not supported by this package') + done(); + }); }); });