Skip to content

Commit bcd1cd2

Browse files
authored
Generate Exceptions (#921)
* Generate Exceptions * Add documentation on top of class * Leverage the new AwsErrorFactory * Fix __constructor signature in GeneratedException * Fix private vs protected * Generate all methods * Fix things * Add constraint in composer.Json * Add changelog entry
1 parent 05c5dac commit bcd1cd2

16 files changed

+270
-22
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
- Changed case of object's properties to camelCase.
88
- Added documentation in class's headers.
9+
- Removed `final` from `ClientException` and `ServerException`.
10+
- Make Responses thrown Business Exception when AwsErrorCode <-> Exception class mapping provided through RequestContext.
11+
- Added Business Exceptions.
912

1013
## 1.8.0
1114

src/AbstractApi.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ final protected function getResponse(Request $request, ?RequestContext $context
167167
]);
168168
}
169169

170-
return new Response($response, $this->httpClient, $this->logger, $this->awsErrorFactory, $debug);
170+
return new Response($response, $this->httpClient, $this->logger, $this->awsErrorFactory, $debug, $context ? $context->getExceptionMapping() : []);
171171
}
172172

173173
/**

src/Exception/Http/ClientException.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
* @author Nicolas Grekas <[email protected]>
1313
*/
14-
final class ClientException extends \RuntimeException implements ClientExceptionInterface, HttpException
14+
class ClientException extends \RuntimeException implements ClientExceptionInterface, HttpException
1515
{
1616
use HttpExceptionTrait;
1717
}

src/Exception/Http/HttpExceptionTrait.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ public function __construct(ResponseInterface $response, AwsError $awsError = nu
4646
}
4747

4848
parent::__construct($message, $code);
49+
50+
$this->populateResult($response);
4951
}
5052

5153
public function getResponse(): ResponseInterface
@@ -72,4 +74,8 @@ public function getAwsDetail(): ?string
7274
{
7375
return $this->awsError ? $this->awsError->getDetail() : null;
7476
}
77+
78+
protected function populateResult(ResponseInterface $response): void
79+
{
80+
}
7581
}

src/Exception/Http/ServerException.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
* @author Nicolas Grekas <[email protected]>
1313
*/
14-
final class ServerException extends \RuntimeException implements HttpException, ServerExceptionInterface
14+
class ServerException extends \RuntimeException implements HttpException, ServerExceptionInterface
1515
{
1616
use HttpExceptionTrait;
1717
}

src/RequestContext.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class RequestContext
1818
'operation' => true,
1919
'expirationDate' => true,
2020
'currentDate' => true,
21+
'exceptionMapping' => true,
2122
];
2223

2324
/**
@@ -40,12 +41,18 @@ class RequestContext
4041
*/
4142
private $currentDate;
4243

44+
/**
45+
* @var array<string, string>
46+
*/
47+
private $exceptionMapping = [];
48+
4349
/**
4450
* @param array{
4551
* operation?: null|string
4652
* region?: null|string
4753
* expirationDate?: null|\DateTimeImmutable
4854
* currentDate?: null|\DateTimeImmutable
55+
* exceptionMapping?: string[]
4956
* }
5057
*/
5158
public function __construct(array $options = [])
@@ -78,4 +85,9 @@ public function getCurrentDate(): ?\DateTimeImmutable
7885
{
7986
return $this->currentDate;
8087
}
88+
89+
public function getExceptionMapping(): array
90+
{
91+
return $this->exceptionMapping;
92+
}
8193
}

src/Response.php

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,19 @@ class Response
8383
*/
8484
private $debug;
8585

86-
public function __construct(ResponseInterface $response, HttpClientInterface $httpClient, LoggerInterface $logger, AwsErrorFactoryInterface $awsErrorFactory = null, bool $debug = false)
86+
/**
87+
* @var array<string, string>
88+
*/
89+
private $exceptionMapping;
90+
91+
public function __construct(ResponseInterface $response, HttpClientInterface $httpClient, LoggerInterface $logger, AwsErrorFactoryInterface $awsErrorFactory = null, bool $debug = false, array $exceptionMapping = [])
8792
{
8893
$this->httpResponse = $response;
8994
$this->httpClient = $httpClient;
9095
$this->logger = $logger;
9196
$this->awsErrorFactory = $awsErrorFactory ?? new ChainAwsErrorFactory();
9297
$this->debug = $debug;
98+
$this->exceptionMapping = $exceptionMapping;
9399
}
94100

95101
public function __destruct()
@@ -373,24 +379,27 @@ private function defineResolveStatus(): void
373379
}
374380

375381
if (300 <= $statusCode) {
376-
$awsErrorFactory = $this->awsErrorFactory;
377-
$httpResponse = $this->httpResponse;
378-
$this->resolveResult = static function () use ($awsErrorFactory, $httpResponse): HttpException {
379-
try {
380-
$awsError = $awsErrorFactory->createFromResponse($httpResponse);
381-
} catch (UnparsableResponse $e) {
382-
$awsError = null;
383-
}
384-
$statusCode = $httpResponse->getStatusCode();
385-
if (500 <= $statusCode) {
386-
return new ServerException($httpResponse, $awsError);
387-
}
382+
try {
383+
$awsError = $this->awsErrorFactory->createFromResponse($this->httpResponse);
384+
} catch (UnparsableResponse $e) {
385+
$awsError = null;
386+
}
388387

389-
if (400 <= $statusCode) {
390-
return new ClientException($httpResponse, $awsError);
391-
}
388+
if ((null !== $awsCode = ($awsError ? $awsError->getCode() : null)) && isset($this->exceptionMapping[$awsCode])) {
389+
$exceptionClass = $this->exceptionMapping[$awsCode];
390+
} elseif (500 <= $statusCode) {
391+
$exceptionClass = ServerException::class;
392+
} elseif (400 <= $statusCode) {
393+
$exceptionClass = ClientException::class;
394+
} else {
395+
$exceptionClass = RedirectionException::class;
396+
}
392397

393-
return new RedirectionException($httpResponse, $awsError);
398+
$httpResponse = $this->httpResponse;
399+
/** @psalm-suppress MoreSpecificReturnType */
400+
$this->resolveResult = static function () use ($exceptionClass, $httpResponse, $awsError): HttpException {
401+
/** @psalm-suppress LessSpecificReturnStatement */
402+
return new $exceptionClass($httpResponse, $awsError);
394403
};
395404

396405
return;

src/Result.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ class Result
2929

3030
private $response;
3131

32+
/**
33+
* @var array<string, string>
34+
*/
35+
private $exceptionMapping;
36+
3237
/**
3338
* @var self[]
3439
*/
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace AsyncAws\Core\Sts\Exception;
4+
5+
use AsyncAws\Core\Exception\Http\ClientException;
6+
use Symfony\Contracts\HttpClient\ResponseInterface;
7+
8+
/**
9+
* The web identity token that was passed is expired or is not valid. Get a new identity token from the identity
10+
* provider and then retry the request.
11+
*/
12+
final class ExpiredTokenException extends ClientException
13+
{
14+
protected function populateResult(ResponseInterface $response): void
15+
{
16+
$data = new \SimpleXMLElement($response->getContent(false));
17+
if (0 < $data->Error->count()) {
18+
$data = $data->Error;
19+
}
20+
if (null !== $v = (($v = $data->message) ? (string) $v : null)) {
21+
$this->message = $v;
22+
}
23+
}
24+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace AsyncAws\Core\Sts\Exception;
4+
5+
use AsyncAws\Core\Exception\Http\ClientException;
6+
use Symfony\Contracts\HttpClient\ResponseInterface;
7+
8+
/**
9+
* The request could not be fulfilled because the identity provider (IDP) that was asked to verify the incoming identity
10+
* token could not be reached. This is often a transient error caused by network conditions. Retry the request a limited
11+
* number of times so that you don't exceed the request rate. If the error persists, the identity provider might be down
12+
* or not responding.
13+
*/
14+
final class IDPCommunicationErrorException extends ClientException
15+
{
16+
protected function populateResult(ResponseInterface $response): void
17+
{
18+
$data = new \SimpleXMLElement($response->getContent(false));
19+
if (0 < $data->Error->count()) {
20+
$data = $data->Error;
21+
}
22+
if (null !== $v = (($v = $data->message) ? (string) $v : null)) {
23+
$this->message = $v;
24+
}
25+
}
26+
}

0 commit comments

Comments
 (0)