Skip to content

Commit dc312a5

Browse files
authored
Merge pull request dingo#1202 from lucasmichot/feature/master/rfc8565
Update RateLimit exception response to RFC6585 specifications
2 parents 950b37f + 9e44767 commit dc312a5

File tree

3 files changed

+39
-6
lines changed

3 files changed

+39
-6
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace Dingo\Api\Exception;
4+
5+
use Exception;
6+
use Symfony\Component\HttpKernel\Exception\HttpException;
7+
8+
class RateLimitExceededException extends HttpException
9+
{
10+
/**
11+
* Create a new rate limit exceeded exception instance.
12+
*
13+
* @param string $message
14+
* @param \Exception $previous
15+
* @param array $headers
16+
* @param int $code
17+
*
18+
* @return void
19+
*/
20+
public function __construct($message = null, Exception $previous = null, $headers = [], $code = 0)
21+
{
22+
if (array_key_exists('X-RateLimit-Reset', $headers)) {
23+
$headers['Retry-After'] = $headers['X-RateLimit-Reset'] - time();
24+
}
25+
26+
parent::__construct(429, $message ?: 'You have exceeded your rate limit.', $previous, $headers, $code);
27+
}
28+
}

src/Http/Middleware/RateLimit.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use Dingo\Api\Routing\Router;
88
use Dingo\Api\Http\InternalRequest;
99
use Dingo\Api\Http\RateLimit\Handler;
10-
use Symfony\Component\HttpKernel\Exception\HttpException;
10+
use Dingo\Api\Exception\RateLimitExceededException;
1111

1212
class RateLimit
1313
{
@@ -64,7 +64,7 @@ public function handle($request, Closure $next)
6464
$this->handler->rateLimitRequest($request, $route->getRateLimit(), $route->getRateLimitExpiration());
6565

6666
if ($this->handler->exceededRateLimit()) {
67-
throw new HttpException(403, 'You have exceeded your rate limit.', null, $this->getHeaders());
67+
throw new RateLimitExceededException('You have exceeded your rate limit.', null, $this->getHeaders());
6868
}
6969

7070
$response = $next($request);

tests/Http/Middleware/RateLimitTest.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Dingo\Api\Http\RateLimit\Handler;
1515
use Dingo\Api\Tests\Stubs\ThrottleStub;
1616
use Dingo\Api\Http\Middleware\RateLimit;
17+
use Dingo\Api\Exception\RateLimitExceededException;
1718
use Symfony\Component\HttpKernel\Exception\HttpException;
1819

1920
class RateLimitTest extends PHPUnit_Framework_TestCase
@@ -125,11 +126,15 @@ public function testRateLimitingFailsAndHeadersAreSetOnException()
125126
return new Response('foo');
126127
});
127128
} catch (HttpException $exception) {
128-
$this->assertSame(403, $exception->getStatusCode());
129+
$this->assertInstanceOf(RateLimitExceededException::class, $exception);
130+
$this->assertSame(429, $exception->getStatusCode());
129131
$this->assertSame('You have exceeded your rate limit.', $exception->getMessage());
130-
$this->assertArrayHasKey('X-RateLimit-Limit', $exception->getHeaders());
131-
$this->assertArrayHasKey('X-RateLimit-Remaining', $exception->getHeaders());
132-
$this->assertArrayHasKey('X-RateLimit-Reset', $exception->getHeaders());
132+
133+
$headers = $exception->getHeaders();
134+
$this->assertSame($headers['X-RateLimit-Reset'] - time(), $headers['Retry-After']);
135+
$this->assertArrayHasKey('X-RateLimit-Limit', $headers);
136+
$this->assertArrayHasKey('X-RateLimit-Remaining', $headers);
137+
$this->assertArrayHasKey('X-RateLimit-Reset', $headers);
133138
}
134139
}
135140

0 commit comments

Comments
 (0)