Skip to content

Commit

Permalink
Fix array cache driver expiry (#48497)
Browse files Browse the repository at this point in the history
  • Loading branch information
timacdonald authored Sep 22, 2023
1 parent 1b88b16 commit ebb780c
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/Illuminate/Cache/ArrayStore.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public function get($key)

$expiresAt = $item['expiresAt'] ?? 0;

if ($expiresAt !== 0 && $this->currentTime() > $expiresAt) {
if ($expiresAt !== 0 && $this->currentTime() >= $expiresAt) {
$this->forget($key);

return;
Expand Down
59 changes: 59 additions & 0 deletions tests/Integration/Http/ThrottleRequestsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Illuminate\Cache\RateLimiter;
use Illuminate\Cache\RateLimiting\GlobalLimit;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Container\Container;
use Illuminate\Http\Exceptions\ThrottleRequestsException;
use Illuminate\Routing\Middleware\ThrottleRequests;
Expand Down Expand Up @@ -116,4 +117,62 @@ public function testItCanGenerateDefinitionViaStaticMethod()
$signature = (string) ThrottleRequests::with(prefix: 'foo');
$this->assertSame('Illuminate\Routing\Middleware\ThrottleRequests:60,1,foo', $signature);
}

public function testItCanThrottlePerMinute()
{
$rateLimiter = Container::getInstance()->make(RateLimiter::class);
$rateLimiter->for('test', fn () => Limit::perMinute(3));
Route::get('/', fn () => 'ok')->middleware(ThrottleRequests::using('test'));

Carbon::setTestNow('2000-01-01 00:00:00.000');

// Make 3 requests, each a second apart, that should all be successful.

for ($i = 0; $i < 3; $i++) {
match ($i) {
0 => $this->assertSame('2000-01-01 00:00:00.000', now()->toDateTimeString('m')),
1 => $this->assertSame('2000-01-01 00:00:01.000', now()->toDateTimeString('m')),
2 => $this->assertSame('2000-01-01 00:00:02.000', now()->toDateTimeString('m')),
};

$response = $this->get('/');
$response->assertOk();
$response->assertContent('ok');
$response->assertHeader('X-RateLimit-Limit', 3);
$response->assertHeader('X-RateLimit-Remaining', 3 - ($i + 1));

Carbon::setTestNow(now()->addSecond());
}

// It is now 3 seconds past and we will make another request that
// should be rate limited.

$this->assertSame('2000-01-01 00:00:03.000', now()->toDateTimeString('m'));

$response = $this->get('/');
$response->assertStatus(429);
$response->assertHeader('Retry-After', 57);
$response->assertHeader('X-RateLimit-Reset', now()->addSeconds(57)->timestamp);
$response->assertHeader('X-RateLimit-Limit', 3);
$response->assertHeader('X-RateLimit-Remaining', 0);

// We will now make it the very end of the minute, to check boundaries,
// and make another request that should be rate limited and tell us to
// try again in 1 second.
Carbon::setTestNow(now()->endOfMinute());
$this->assertSame('2000-01-01 00:00:59.999', now()->toDateTimeString('m'));

$response = $this->get('/');
$response->assertHeader('Retry-After', 1);
$response->assertHeader('X-RateLimit-Reset', now()->addSeconds(1)->timestamp);
$response->assertHeader('X-RateLimit-Limit', 3);
$response->assertHeader('X-RateLimit-Remaining', 0);

// We now tick over into the next second. We should now be able to make
// requests again.
Carbon::setTestNow('2000-01-01 00:01:00.000');

$response = $this->get('/');
$response->assertOk();
}
}

0 comments on commit ebb780c

Please sign in to comment.