Skip to content

Commit 7bbf258

Browse files
committed
feat: Handle TooManyRequestsHttpException
1 parent 95f1ad2 commit 7bbf258

File tree

4 files changed

+119
-0
lines changed

4 files changed

+119
-0
lines changed

spec/Client/HttpExceptionHandlerSpec.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Akeneo\Pim\ApiClient\Exception\NotFoundHttpException;
1111
use Akeneo\Pim\ApiClient\Exception\RedirectionHttpException;
1212
use Akeneo\Pim\ApiClient\Exception\ServerErrorHttpException;
13+
use Akeneo\Pim\ApiClient\Exception\TooManyRequestsHttpException;
1314
use Akeneo\Pim\ApiClient\Exception\UnauthorizedHttpException;
1415
use Akeneo\Pim\ApiClient\Exception\UnprocessableEntityHttpException;
1516
use Akeneo\Pim\ApiClient\Client\HttpExceptionHandler;
@@ -221,6 +222,26 @@ function it_throws_bad_request_exception_when_status_code_422(
221222
->during('transformResponseToException', [$request, $response]);
222223
}
223224

225+
function it_throws_bad_request_exception_when_status_code_429(
226+
RequestInterface $request,
227+
ResponseInterface $response,
228+
StreamInterface $responseBody
229+
) {
230+
$response->getStatusCode()->willReturn(429);
231+
$response->getBody()->willReturn($responseBody);
232+
$responseBody->getContents()->willReturn('Too Many Requests');
233+
$responseBody->getContents()->shouldBeCalled();
234+
$this
235+
->shouldThrow(
236+
new TooManyRequestsHttpException(
237+
'Too Many Requests',
238+
$request->getWrappedObject(),
239+
$response->getWrappedObject()
240+
)
241+
)
242+
->during('transformResponseToException', [$request, $response]);
243+
}
244+
224245
function it_throws_bad_request_exception_when_status_code_4xx(
225246
RequestInterface $request,
226247
ResponseInterface $response,

src/Client/HttpExceptionHandler.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Akeneo\Pim\ApiClient\Exception\NotFoundHttpException;
1111
use Akeneo\Pim\ApiClient\Exception\RedirectionHttpException;
1212
use Akeneo\Pim\ApiClient\Exception\ServerErrorHttpException;
13+
use Akeneo\Pim\ApiClient\Exception\TooManyRequestsHttpException;
1314
use Akeneo\Pim\ApiClient\Exception\UnauthorizedHttpException;
1415
use Akeneo\Pim\ApiClient\Exception\UnprocessableEntityHttpException;
1516
use Akeneo\Pim\ApiClient\Exception\UnsupportedMediaTypeHttpException;
@@ -80,6 +81,10 @@ public function transformResponseToException(
8081
throw new UnprocessableEntityHttpException($this->getResponseMessage($response), $request, $response);
8182
}
8283

84+
if (HttpClient::HTTP_TOO_MANY_REQUESTS === $response->getStatusCode()) {
85+
throw new TooManyRequestsHttpException($response->getBody()->getContents(), $request, $response);
86+
}
87+
8388
if ($this->isApiClientErrorStatusCode($response->getStatusCode())) {
8489
throw new ClientErrorHttpException($this->getResponseMessage($response), $request, $response);
8590
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace Akeneo\Pim\ApiClient\Exception;
4+
5+
/**
6+
* @copyright 2022 Akeneo SAS (https://www.akeneo.com)
7+
* @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
8+
*/
9+
class TooManyRequestsHttpException extends ClientErrorHttpException
10+
{
11+
/**
12+
* How much time must be waited before next request. Result in seconds.
13+
*/
14+
public function getRetryAfter(): int
15+
{
16+
$response = $this->getResponse();
17+
18+
if (!$response->hasHeader('Retry-After')) {
19+
throw new RuntimeException('Cannot find Retry-After header.');
20+
}
21+
22+
$retryAfter = $response->getHeader('Retry-After')[0];
23+
24+
if (preg_match('/^\d+$/', $retryAfter)) {
25+
return (int) $retryAfter;
26+
}
27+
28+
throw new RuntimeException('Cannot parse Retry-After header. Value must be seconds.');
29+
}
30+
31+
protected function getAdditionalInformationMessage(): string
32+
{
33+
return '(see https://api.akeneo.com/php-client/exception.html#too-many-requests-exception)';
34+
}
35+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
namespace Akeneo\Pim\ApiClient\tests\Exception;
4+
5+
use Akeneo\Pim\ApiClient\Exception\RuntimeException;
6+
use Akeneo\Pim\ApiClient\Exception\TooManyRequestsHttpException;
7+
use PHPUnit\Framework\TestCase;
8+
use Psr\Http\Message\RequestInterface;
9+
use Psr\Http\Message\ResponseInterface;
10+
11+
class TooManyRequestsHttpExceptionTest extends TestCase
12+
{
13+
private RequestInterface $request;
14+
15+
public function setUp(): void
16+
{
17+
$this->request = $this->createMock(RequestInterface::class);
18+
}
19+
20+
public function testRetryAfter(): void
21+
{
22+
$response = $this->createMock(ResponseInterface::class);
23+
$response->method('hasHeader')->willReturn(true);
24+
$response->method('getHeader')->willReturn(['10']);
25+
26+
$exception = new TooManyRequestsHttpException('Too Many Requests', $this->request, $response, null);
27+
28+
$this->assertSame(
29+
10,
30+
$exception->getRetryAfter()
31+
);
32+
}
33+
34+
public function testCannotFindRetryAfterHeader(): void
35+
{
36+
$response = $this->createMock(ResponseInterface::class);
37+
$response->method('hasHeader')->willReturn(false);
38+
39+
$exception = new TooManyRequestsHttpException('Too Many Requests', $this->request, $response, null);
40+
41+
$this->expectException(RuntimeException::class);
42+
43+
$exception->getRetryAfter();
44+
}
45+
46+
public function testCannotParseRetryAfterHeader(): void
47+
{
48+
$response = $this->createMock(ResponseInterface::class);
49+
$response->method('hasHeader')->willReturn(true);
50+
$response->method('getHeader')->willReturn([0 => 'Wed, 21 Oct 2015 07:28:00 GMT']);
51+
52+
$exception = new TooManyRequestsHttpException('Too Many Requests', $this->request, $response, null);
53+
54+
$this->expectException(RuntimeException::class);
55+
56+
$exception->getRetryAfter();
57+
}
58+
}

0 commit comments

Comments
 (0)