Skip to content

Commit 4f23c78

Browse files
committed
Fix the RateLimite issue when generating dynamic keys
1 parent 7db7ea9 commit 4f23c78

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

src/Illuminate/Cache/RateLimiter.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ public function limiter($name)
8585

8686
foreach ($result as $limit) {
8787
if ($duplicates->contains($limit->key)) {
88-
$limit->key = $limit->fallbackKey();
88+
$limit->key = empty($limit->key)
89+
? $limit->fallbackKey()
90+
: $limit->key.':'.$limit->fallbackKey();
8991
}
9092
}
9193

tests/Cache/RateLimiterTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
namespace Illuminate\Tests\Cache;
44

5+
use Illuminate\Cache\ArrayStore;
56
use Illuminate\Cache\RateLimiter;
67
use Illuminate\Cache\RateLimiting\Limit;
8+
use Illuminate\Cache\Repository;
79
use Illuminate\Contracts\Cache\Repository as Cache;
810
use PHPUnit\Framework\Attributes\DataProvider;
911
use PHPUnit\Framework\TestCase;
@@ -38,6 +40,33 @@ public function testRegisterNamedRateLimiter(mixed $name, string $expected): voi
3840

3941
$this->assertNotNull($limiterClosure);
4042
}
43+
44+
public function testShouldUseOriginKeyAsPrefixWhenMultipleLimiterWithSameKey()
45+
{
46+
$rateLimiter = new RateLimiter(new Repository(new ArrayStore));
47+
48+
$rateLimiter->for('user_limiter', fn (string $userId) => [
49+
Limit::perSecond(3)->by($userId),
50+
Limit::perMinute(5)->by($userId),
51+
]);
52+
53+
$userId1 = '123';
54+
$userId2 = '456';
55+
56+
$limiterForUser1 = $rateLimiter->limiter('user_limiter')($userId1);
57+
$limiterForUser2 = $rateLimiter->limiter('user_limiter')($userId2);
58+
59+
for ($i = 0; $i < 3; $i++) {
60+
$this->assertFalse($rateLimiter->tooManyAttempts($limiterForUser1[0]->key, $limiterForUser1[0]->maxAttempts));
61+
$this->assertFalse($rateLimiter->tooManyAttempts($limiterForUser2[0]->key, $limiterForUser2[0]->maxAttempts));
62+
63+
$rateLimiter->hit($limiterForUser1[0]->key, $limiterForUser1[0]->decaySeconds);
64+
$rateLimiter->hit($limiterForUser2[0]->key, $limiterForUser2[0]->decaySeconds);
65+
}
66+
67+
$this->assertNotSame($limiterForUser1[0]->key, $limiterForUser2[0]->key);
68+
$this->assertNotSame($limiterForUser1[1]->key, $limiterForUser2[1]->key);
69+
}
4170
}
4271

4372
enum BackedEnumNamedRateLimiter: string

0 commit comments

Comments
 (0)