Skip to content

Commit 211b1f2

Browse files
authored
Add supports for multi-region (#466)
* Allow custom region at run time * Regenerate code * Add changelog entry * Add docbloc on Input without members
1 parent aed5269 commit 211b1f2

File tree

8 files changed

+78
-23
lines changed

8 files changed

+78
-23
lines changed

CHANGELOG.md

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

33
## 0.5.0
44

5+
### Added
6+
7+
- Add support for multiregion via `@region` input parameter.
8+
59
### Changed
610

711
- The `StreamableBodyInterface::getChunks` now returns a iterrable of string.

src/AbstractApi.php

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ abstract class AbstractApi
4444
private $credentialProvider;
4545

4646
/**
47-
* @var Signer
47+
* @var Signer[]
4848
*/
49-
private $signer;
49+
private $signers;
5050

5151
/**
5252
* @param Configuration|array $configuration
@@ -78,10 +78,10 @@ final public function getConfiguration(): Configuration
7878
final public function presign(Input $input, ?\DateTimeImmutable $expires = null): string
7979
{
8080
$request = $input->request();
81-
$request->setEndpoint($this->getEndpoint($request->getUri(), $request->getQuery()));
81+
$request->setEndpoint($this->getEndpoint($request->getUri(), $request->getQuery(), $input->getRegion()));
8282

8383
if (null !== $credentials = $this->credentialProvider->getCredentials($this->configuration)) {
84-
$this->getSigner()->presign($request, $credentials, new RequestContext(['expirationDate' => $expires]));
84+
$this->getSigner($input->getRegion())->presign($request, $credentials, new RequestContext(['expirationDate' => $expires]));
8585
}
8686

8787
return $request->getEndpoint();
@@ -95,10 +95,10 @@ abstract protected function getSignatureScopeName(): string;
9595

9696
final protected function getResponse(Request $request, ?RequestContext $context = null): Response
9797
{
98-
$request->setEndpoint($this->getEndpoint($request->getUri(), $request->getQuery()));
98+
$request->setEndpoint($this->getEndpoint($request->getUri(), $request->getQuery(), $context ? $context->getRegion() : null));
9999

100100
if (null !== $credentials = $this->credentialProvider->getCredentials($this->configuration)) {
101-
$this->getSigner()->sign($request, $credentials, $context ?? new RequestContext());
101+
$this->getSigner($context ? $context->getRegion() : null)->sign($request, $credentials, $context ?? new RequestContext());
102102
}
103103

104104
$length = $request->getBody()->length();
@@ -142,11 +142,11 @@ protected function getSignerFactories(): array
142142
* @param string $uri or path
143143
* @param array $query parameters that should go in the query string
144144
*/
145-
private function getEndpoint(string $uri, array $query): string
145+
private function getEndpoint(string $uri, array $query, ?string $region): string
146146
{
147147
/** @psalm-suppress PossiblyNullArgument */
148148
$endpoint = strtr($this->configuration->get('endpoint'), [
149-
'%region%' => $this->configuration->get('region'),
149+
'%region%' => $region ?? $this->configuration->get('region'),
150150
'%service%' => $this->getServiceCode(),
151151
]);
152152
$endpoint .= $uri;
@@ -157,19 +157,20 @@ private function getEndpoint(string $uri, array $query): string
157157
return $endpoint . (false === \strpos($endpoint, '?') ? '?' : '&') . http_build_query($query);
158158
}
159159

160-
private function getSigner()
160+
private function getSigner(?string $region)
161161
{
162-
if (null === $this->signer) {
162+
if (!isset($this->signers[$region])) {
163163
/** @var string $region */
164-
$region = $this->configuration->get(Configuration::OPTION_REGION);
164+
$region = $region ?? $this->configuration->get(Configuration::OPTION_REGION);
165165
$factories = $this->getSignerFactories();
166166
if (!isset($factories[$signatureVersion = $this->getSignatureVersion()])) {
167167
throw new InvalidArgument(sprintf('The signature "%s" is not implemented.', $signatureVersion));
168168
}
169169

170-
$this->signer = $factories[$signatureVersion]($this->getSignatureScopeName(), $region);
170+
$this->signers[$region] = $factories[$signatureVersion]($this->getSignatureScopeName(), $region);
171171
}
172172

173-
return $this->signer;
173+
/** @psalm-suppress PossiblyNullArrayOffset */
174+
return $this->signers[$region];
174175
}
175176
}

src/Input.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,24 @@
99
*
1010
* @internal
1111
*/
12-
interface Input
12+
abstract class Input
1313
{
14-
public function request(): Request;
14+
public $region;
15+
16+
/**
17+
* @param array{
18+
* @region?: ?string,
19+
* } $input
20+
*/
21+
protected function __construct(array $input)
22+
{
23+
$this->region = $input['@region'] ?? null;
24+
}
25+
26+
public function getRegion(): ?string
27+
{
28+
return $this->region;
29+
}
30+
31+
abstract public function request(): Request;
1532
}

src/RequestContext.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
class RequestContext
1515
{
1616
public const AVAILABLE_OPTIONS = [
17+
'region' => true,
1718
'operation' => true,
1819
'expirationDate' => true,
1920
'currentDate' => true,
@@ -24,6 +25,11 @@ class RequestContext
2425
*/
2526
private $operation;
2627

28+
/**
29+
* @var string|null
30+
*/
31+
private $region;
32+
2733
/**
2834
* @var \DateTimeImmutable|null
2935
*/
@@ -37,6 +43,7 @@ class RequestContext
3743
/**
3844
* @param array{
3945
* operation?: null|string
46+
* region?: null|string
4047
* expirationDate?: null|\DateTimeImmutable
4148
* currentDate?: null|\DateTimeImmutable
4249
* }
@@ -57,6 +64,11 @@ public function getOperation(): ?string
5764
return $this->operation;
5865
}
5966

67+
public function getRegion(): ?string
68+
{
69+
return $this->region;
70+
}
71+
6072
public function getExpirationDate(): ?\DateTimeImmutable
6173
{
6274
return $this->expirationDate;

src/Sts/Input/AssumeRoleRequest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
use AsyncAws\Core\Sts\ValueObject\PolicyDescriptorType;
1010
use AsyncAws\Core\Sts\ValueObject\Tag;
1111

12-
final class AssumeRoleRequest implements Input
12+
final class AssumeRoleRequest extends Input
1313
{
1414
/**
1515
* The Amazon Resource Name (ARN) of the role to assume.
@@ -124,6 +124,7 @@ final class AssumeRoleRequest implements Input
124124
* ExternalId?: string,
125125
* SerialNumber?: string,
126126
* TokenCode?: string,
127+
* @region?: string,
127128
* } $input
128129
*/
129130
public function __construct(array $input = [])
@@ -138,6 +139,7 @@ public function __construct(array $input = [])
138139
$this->ExternalId = $input['ExternalId'] ?? null;
139140
$this->SerialNumber = $input['SerialNumber'] ?? null;
140141
$this->TokenCode = $input['TokenCode'] ?? null;
142+
parent::__construct($input);
141143
}
142144

143145
public static function create($input): self

src/Sts/Input/AssumeRoleWithWebIdentityRequest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use AsyncAws\Core\Stream\StreamFactory;
99
use AsyncAws\Core\Sts\ValueObject\PolicyDescriptorType;
1010

11-
final class AssumeRoleWithWebIdentityRequest implements Input
11+
final class AssumeRoleWithWebIdentityRequest extends Input
1212
{
1313
/**
1414
* The Amazon Resource Name (ARN) of the role that the caller is assuming.
@@ -86,6 +86,7 @@ final class AssumeRoleWithWebIdentityRequest implements Input
8686
* PolicyArns?: \AsyncAws\Core\Sts\ValueObject\PolicyDescriptorType[],
8787
* Policy?: string,
8888
* DurationSeconds?: int,
89+
* @region?: string,
8990
* } $input
9091
*/
9192
public function __construct(array $input = [])
@@ -97,6 +98,7 @@ public function __construct(array $input = [])
9798
$this->PolicyArns = array_map([PolicyDescriptorType::class, 'create'], $input['PolicyArns'] ?? []);
9899
$this->Policy = $input['Policy'] ?? null;
99100
$this->DurationSeconds = $input['DurationSeconds'] ?? null;
101+
parent::__construct($input);
100102
}
101103

102104
public static function create($input): self

src/Sts/Input/GetCallerIdentityRequest.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,21 @@
66
use AsyncAws\Core\Request;
77
use AsyncAws\Core\Stream\StreamFactory;
88

9-
final class GetCallerIdentityRequest implements Input
9+
final class GetCallerIdentityRequest extends Input
1010
{
11+
/**
12+
* @param array{
13+
* @region?: string,
14+
* } $input
15+
*/
16+
public function __construct(array $input = [])
17+
{
18+
parent::__construct($input);
19+
}
20+
1121
public static function create($input): self
1222
{
13-
return $input instanceof self ? $input : new self();
23+
return $input instanceof self ? $input : new self($input);
1424
}
1525

1626
/**

src/Sts/StsClient.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,13 @@ class StsClient extends AbstractApi
3535
* ExternalId?: string,
3636
* SerialNumber?: string,
3737
* TokenCode?: string,
38+
* @region?: string,
3839
* }|AssumeRoleRequest $input
3940
*/
4041
public function assumeRole($input): AssumeRoleResponse
4142
{
42-
$response = $this->getResponse(AssumeRoleRequest::create($input)->request(), new RequestContext(['operation' => 'AssumeRole']));
43+
$input = AssumeRoleRequest::create($input);
44+
$response = $this->getResponse($input->request(), new RequestContext(['operation' => 'AssumeRole', 'region' => $input->getRegion()]));
4345

4446
return new AssumeRoleResponse($response);
4547
}
@@ -59,11 +61,13 @@ public function assumeRole($input): AssumeRoleResponse
5961
* PolicyArns?: \AsyncAws\Core\Sts\ValueObject\PolicyDescriptorType[],
6062
* Policy?: string,
6163
* DurationSeconds?: int,
64+
* @region?: string,
6265
* }|AssumeRoleWithWebIdentityRequest $input
6366
*/
6467
public function assumeRoleWithWebIdentity($input): AssumeRoleWithWebIdentityResponse
6568
{
66-
$response = $this->getResponse(AssumeRoleWithWebIdentityRequest::create($input)->request(), new RequestContext(['operation' => 'AssumeRoleWithWebIdentity']));
69+
$input = AssumeRoleWithWebIdentityRequest::create($input);
70+
$response = $this->getResponse($input->request(), new RequestContext(['operation' => 'AssumeRoleWithWebIdentity', 'region' => $input->getRegion()]));
6771

6872
return new AssumeRoleWithWebIdentityResponse($response);
6973
}
@@ -73,11 +77,14 @@ public function assumeRoleWithWebIdentity($input): AssumeRoleWithWebIdentityResp
7377
*
7478
* @see https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-sts-2011-06-15.html#getcalleridentity
7579
*
76-
* @param array|GetCallerIdentityRequest $input
80+
* @param array{
81+
* @region?: string,
82+
* }|GetCallerIdentityRequest $input
7783
*/
7884
public function getCallerIdentity($input = []): GetCallerIdentityResponse
7985
{
80-
$response = $this->getResponse(GetCallerIdentityRequest::create($input)->request(), new RequestContext(['operation' => 'GetCallerIdentity']));
86+
$input = GetCallerIdentityRequest::create($input);
87+
$response = $this->getResponse($input->request(), new RequestContext(['operation' => 'GetCallerIdentity', 'region' => $input->getRegion()]));
8188

8289
return new GetCallerIdentityResponse($response);
8390
}

0 commit comments

Comments
 (0)