From 5a3602a85a290d34066b762c2dc898600aad4f75 Mon Sep 17 00:00:00 2001 From: Seb Date: Mon, 6 Nov 2023 13:08:07 -0800 Subject: [PATCH 1/7] Allow ratelimiter custom increments --- src/Illuminate/Cache/RateLimiter.php | 30 +++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/Illuminate/Cache/RateLimiter.php b/src/Illuminate/Cache/RateLimiter.php index 5f5fac0659b6..af1f3989c6f3 100644 --- a/src/Illuminate/Cache/RateLimiter.php +++ b/src/Illuminate/Cache/RateLimiter.php @@ -94,7 +94,7 @@ public function attempt($key, $maxAttempts, Closure $callback, $decaySeconds = 6 public function tooManyAttempts($key, $maxAttempts) { if ($this->attempts($key) >= $maxAttempts) { - if ($this->cache->has($this->cleanRateLimiterKey($key).':timer')) { + if ($this->cache->has($this->cleanRateLimiterKey($key) . ':timer')) { return true; } @@ -105,25 +105,41 @@ public function tooManyAttempts($key, $maxAttempts) } /** - * Increment the counter for a given key for a given decay time. + * Increment (by 1) the counter for a given key for a given decay time. * * @param string $key * @param int $decaySeconds * @return int */ public function hit($key, $decaySeconds = 60) + { + return $this->increment($key, $decaySeconds); + } + + /** + * Increment the counter for a given key for a given decay time by a custom + * amount. + * + * @param string $key + * @param int $decaySeconds + * @param int $step + * @return int + */ + public function increment($key, $decaySeconds = 60, $step = 1) { $key = $this->cleanRateLimiterKey($key); $this->cache->add( - $key.':timer', $this->availableAt($decaySeconds), $decaySeconds + $key . ':timer', + $this->availableAt($decaySeconds), + $decaySeconds ); $added = $this->cache->add($key, 0, $decaySeconds); - $hits = (int) $this->cache->increment($key); + $hits = (int) $this->cache->increment($key, $step); - if (! $added && $hits == 1) { + if (!$added && $hits == 1) { $this->cache->put($key, 1, $decaySeconds); } @@ -196,7 +212,7 @@ public function clear($key) $this->resetAttempts($key); - $this->cache->forget($key.':timer'); + $this->cache->forget($key . ':timer'); } /** @@ -209,7 +225,7 @@ public function availableIn($key) { $key = $this->cleanRateLimiterKey($key); - return max(0, $this->cache->get($key.':timer') - $this->currentTime()); + return max(0, $this->cache->get($key . ':timer') - $this->currentTime()); } /** From e4c033a01c30067ed0a833e58904dcc8bef03661 Mon Sep 17 00:00:00 2001 From: Seb Date: Mon, 6 Nov 2023 13:36:08 -0800 Subject: [PATCH 2/7] add test --- tests/Cache/CacheRateLimiterTest.php | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/tests/Cache/CacheRateLimiterTest.php b/tests/Cache/CacheRateLimiterTest.php index 660179256c84..df48190f35ac 100644 --- a/tests/Cache/CacheRateLimiterTest.php +++ b/tests/Cache/CacheRateLimiterTest.php @@ -7,6 +7,9 @@ use Mockery as m; use PHPUnit\Framework\TestCase; +/** + * @group debug + */ class CacheRateLimiterTest extends TestCase { protected function tearDown(): void @@ -30,18 +33,29 @@ public function testHitProperlyIncrementsAttemptCount() $cache = m::mock(Cache::class); $cache->shouldReceive('add')->once()->with('key:timer', m::type('int'), 1)->andReturn(true); $cache->shouldReceive('add')->once()->with('key', 0, 1)->andReturn(true); - $cache->shouldReceive('increment')->once()->with('key')->andReturn(1); + $cache->shouldReceive('increment')->once()->with('key', 1)->andReturn(1); $rateLimiter = new RateLimiter($cache); $rateLimiter->hit('key', 1); } + public function testIncrementProperlyIncrementsAttemptCount() + { + $cache = m::mock(Cache::class); + $cache->shouldReceive('add')->once()->with('key:timer', m::type('int'), 1)->andReturn(true); + $cache->shouldReceive('add')->once()->with('key', 0, 1)->andReturn(true); + $cache->shouldReceive('increment')->once()->with('key', 5)->andReturn(5); + $rateLimiter = new RateLimiter($cache); + + $rateLimiter->increment('key', 1, 5); + } + public function testHitHasNoMemoryLeak() { $cache = m::mock(Cache::class); $cache->shouldReceive('add')->once()->with('key:timer', m::type('int'), 1)->andReturn(true); $cache->shouldReceive('add')->once()->with('key', 0, 1)->andReturn(false); - $cache->shouldReceive('increment')->once()->with('key')->andReturn(1); + $cache->shouldReceive('increment')->once()->with('key', 1)->andReturn(1); $cache->shouldReceive('put')->once()->with('key', 1, 1); $rateLimiter = new RateLimiter($cache); @@ -83,7 +97,7 @@ public function testAttemptsCallbackReturnsTrue() $cache->shouldReceive('get')->once()->with('key', 0)->andReturn(0); $cache->shouldReceive('add')->once()->with('key:timer', m::type('int'), 1); $cache->shouldReceive('add')->once()->with('key', 0, 1)->andReturns(1); - $cache->shouldReceive('increment')->once()->with('key')->andReturn(1); + $cache->shouldReceive('increment')->once()->with('key', 1)->andReturn(1); $executed = false; @@ -101,7 +115,7 @@ public function testAttemptsCallbackReturnsCallbackReturn() $cache->shouldReceive('get')->times(6)->with('key', 0)->andReturn(0); $cache->shouldReceive('add')->times(6)->with('key:timer', m::type('int'), 1); $cache->shouldReceive('add')->times(6)->with('key', 0, 1)->andReturns(1); - $cache->shouldReceive('increment')->times(6)->with('key')->andReturn(1); + $cache->shouldReceive('increment')->times(6)->with('key', 1)->andReturn(1); $rateLimiter = new RateLimiter($cache); From fe24751ee1d99d2601ac1271401c860de930a794 Mon Sep 17 00:00:00 2001 From: Sebastien Armand Date: Wed, 21 Feb 2024 15:19:07 -0800 Subject: [PATCH 3/7] formatting --- src/Illuminate/Cache/RateLimiter.php | 6 +++--- tests/Cache/CacheRateLimiterTest.php | 3 --- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Illuminate/Cache/RateLimiter.php b/src/Illuminate/Cache/RateLimiter.php index af1f3989c6f3..3d82985840aa 100644 --- a/src/Illuminate/Cache/RateLimiter.php +++ b/src/Illuminate/Cache/RateLimiter.php @@ -94,7 +94,7 @@ public function attempt($key, $maxAttempts, Closure $callback, $decaySeconds = 6 public function tooManyAttempts($key, $maxAttempts) { if ($this->attempts($key) >= $maxAttempts) { - if ($this->cache->has($this->cleanRateLimiterKey($key) . ':timer')) { + if ($this->cache->has($this->cleanRateLimiterKey($key).':timer')) { return true; } @@ -212,7 +212,7 @@ public function clear($key) $this->resetAttempts($key); - $this->cache->forget($key . ':timer'); + $this->cache->forget($key.':timer'); } /** @@ -225,7 +225,7 @@ public function availableIn($key) { $key = $this->cleanRateLimiterKey($key); - return max(0, $this->cache->get($key . ':timer') - $this->currentTime()); + return max(0, $this->cache->get($key.':timer') - $this->currentTime()); } /** diff --git a/tests/Cache/CacheRateLimiterTest.php b/tests/Cache/CacheRateLimiterTest.php index df48190f35ac..0805f92af092 100644 --- a/tests/Cache/CacheRateLimiterTest.php +++ b/tests/Cache/CacheRateLimiterTest.php @@ -7,9 +7,6 @@ use Mockery as m; use PHPUnit\Framework\TestCase; -/** - * @group debug - */ class CacheRateLimiterTest extends TestCase { protected function tearDown(): void From bc3ea86cf083c12726da140bb0270af8abb36d85 Mon Sep 17 00:00:00 2001 From: Sebastien Armand Date: Wed, 21 Feb 2024 15:31:07 -0800 Subject: [PATCH 4/7] formatting --- src/Illuminate/Cache/RateLimiter.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Illuminate/Cache/RateLimiter.php b/src/Illuminate/Cache/RateLimiter.php index 3d82985840aa..d786887b058f 100644 --- a/src/Illuminate/Cache/RateLimiter.php +++ b/src/Illuminate/Cache/RateLimiter.php @@ -120,9 +120,9 @@ public function hit($key, $decaySeconds = 60) * Increment the counter for a given key for a given decay time by a custom * amount. * - * @param string $key - * @param int $decaySeconds - * @param int $step + * @param string $key + * @param int $decaySeconds + * @param int $step * @return int */ public function increment($key, $decaySeconds = 60, $step = 1) @@ -130,7 +130,7 @@ public function increment($key, $decaySeconds = 60, $step = 1) $key = $this->cleanRateLimiterKey($key); $this->cache->add( - $key . ':timer', + $key.':timer', $this->availableAt($decaySeconds), $decaySeconds ); @@ -139,7 +139,7 @@ public function increment($key, $decaySeconds = 60, $step = 1) $hits = (int) $this->cache->increment($key, $step); - if (!$added && $hits == 1) { + if (! $added && $hits == 1) { $this->cache->put($key, 1, $decaySeconds); } From d804b1f500c787183d01cef195a2272ff4bca3dc Mon Sep 17 00:00:00 2001 From: Tim MacDonald Date: Thu, 22 Feb 2024 12:25:16 +1100 Subject: [PATCH 5/7] Revert formatting --- src/Illuminate/Cache/RateLimiter.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Illuminate/Cache/RateLimiter.php b/src/Illuminate/Cache/RateLimiter.php index d786887b058f..c8276cb726bd 100644 --- a/src/Illuminate/Cache/RateLimiter.php +++ b/src/Illuminate/Cache/RateLimiter.php @@ -130,9 +130,7 @@ public function increment($key, $decaySeconds = 60, $step = 1) $key = $this->cleanRateLimiterKey($key); $this->cache->add( - $key.':timer', - $this->availableAt($decaySeconds), - $decaySeconds + $key.':timer', $this->availableAt($decaySeconds), $decaySeconds ); $added = $this->cache->add($key, 0, $decaySeconds); From 46c60269749c03267afc36ee8b07b365f2c95029 Mon Sep 17 00:00:00 2001 From: Tim MacDonald Date: Thu, 22 Feb 2024 12:28:02 +1100 Subject: [PATCH 6/7] Formatting --- src/Illuminate/Cache/RateLimiter.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Illuminate/Cache/RateLimiter.php b/src/Illuminate/Cache/RateLimiter.php index c8276cb726bd..0315da050194 100644 --- a/src/Illuminate/Cache/RateLimiter.php +++ b/src/Illuminate/Cache/RateLimiter.php @@ -117,8 +117,7 @@ public function hit($key, $decaySeconds = 60) } /** - * Increment the counter for a given key for a given decay time by a custom - * amount. + * Increment the counter for a given key for a given decay time by a custom amount. * * @param string $key * @param int $decaySeconds From 430ad68cdd9dd9a0957a7df1820a1e9d27845dd8 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Sun, 25 Feb 2024 08:42:05 -0600 Subject: [PATCH 7/7] formatting --- src/Illuminate/Cache/RateLimiter.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Illuminate/Cache/RateLimiter.php b/src/Illuminate/Cache/RateLimiter.php index 0315da050194..afdb9b25a208 100644 --- a/src/Illuminate/Cache/RateLimiter.php +++ b/src/Illuminate/Cache/RateLimiter.php @@ -117,14 +117,14 @@ public function hit($key, $decaySeconds = 60) } /** - * Increment the counter for a given key for a given decay time by a custom amount. + * Increment the counter for a given key for a given decay time by a given amount. * * @param string $key * @param int $decaySeconds - * @param int $step + * @param int $amount * @return int */ - public function increment($key, $decaySeconds = 60, $step = 1) + public function increment($key, $decaySeconds = 60, $amount = 1) { $key = $this->cleanRateLimiterKey($key); @@ -134,7 +134,7 @@ public function increment($key, $decaySeconds = 60, $step = 1) $added = $this->cache->add($key, 0, $decaySeconds); - $hits = (int) $this->cache->increment($key, $step); + $hits = (int) $this->cache->increment($key, $amount); if (! $added && $hits == 1) { $this->cache->put($key, 1, $decaySeconds);