Skip to content
/ core Public

Commit 70e6b62

Browse files
authored
Add support for Lists in querystring (#2018)
1 parent c13e794 commit 70e6b62

3 files changed

Lines changed: 61 additions & 13 deletions

File tree

src/AbstractApi.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use AsyncAws\Core\Exception\LogicException;
1616
use AsyncAws\Core\Exception\RuntimeException;
1717
use AsyncAws\Core\HttpClient\AwsRetryStrategy;
18+
use AsyncAws\Core\HttpClient\BuildHttpQueryTrait;
1819
use AsyncAws\Core\Signer\Signer;
1920
use AsyncAws\Core\Signer\SignerV4;
2021
use AsyncAws\Core\Stream\StringStream;
@@ -32,6 +33,8 @@
3233
*/
3334
abstract class AbstractApi
3435
{
36+
use BuildHttpQueryTrait;
37+
3538
/**
3639
* @var HttpClientInterface
3740
*/
@@ -230,9 +233,9 @@ protected function getEndpointMetadata(?string $region): array
230233
/**
231234
* Build the endpoint full uri.
232235
*
233-
* @param string $uri or path
234-
* @param array<string, string> $query parameters that should go in the query string
235-
* @param ?string $region region provided by the user in the `@region` parameter of the Input
236+
* @param string $uri or path
237+
* @param array<string, string|string[]> $query parameters that should go in the query string
238+
* @param ?string $region region provided by the user in the `@region` parameter of the Input
236239
*/
237240
protected function getEndpoint(string $uri, array $query, ?string $region): string
238241
{
@@ -260,7 +263,7 @@ protected function getEndpoint(string $uri, array $query, ?string $region): stri
260263
return $endpoint;
261264
}
262265

263-
return $endpoint . (false === strpos($endpoint, '?') ? '?' : '&') . http_build_query($query, '', '&', \PHP_QUERY_RFC3986);
266+
return $endpoint . (false === strpos($endpoint, '?') ? '?' : '&') . $this->buildHttpQuery($query);
264267
}
265268

266269
/**
@@ -272,7 +275,7 @@ protected function discoverEndpoints(?string $region): array
272275
}
273276

274277
/**
275-
* @param array<string, string> $query
278+
* @param array<string, string|string[]> $query
276279
*
277280
* @return string
278281
*/
@@ -316,7 +319,7 @@ private function getDiscoveredEndpoint(string $uri, array $query, ?string $regio
316319
return $endpoint;
317320
}
318321

319-
return $endpoint . (false === strpos($endpoint, '?') ? '?' : '&') . http_build_query($query);
322+
return $endpoint . (false === strpos($endpoint, '?') ? '?' : '&') . $this->buildHttpQuery($query);
320323
}
321324

322325
/**
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
namespace AsyncAws\Core\HttpClient;
4+
5+
/**
6+
* @author Jérémy Derussé <jeremy@derusse.com>
7+
*/
8+
trait BuildHttpQueryTrait
9+
{
10+
/**
11+
* Build a query string from an array of key value pairs
12+
* This function does not modify the provided keys when an array is encountered (like `http_build_query()` would).
13+
*
14+
* @param array<string, string|string[]> $query
15+
*/
16+
private function buildHttpQuery(array $query): string
17+
{
18+
if (empty($query)) {
19+
return '';
20+
}
21+
22+
$qs = '';
23+
foreach ($query as $k => $v) {
24+
$k = rawurlencode($k);
25+
if (!\is_array($v)) {
26+
$qs .= $k . '=' . rawurlencode($v) . '&';
27+
} else {
28+
foreach ($v as $vv) {
29+
$qs .= $k . '=' . rawurlencode($vv) . '&';
30+
}
31+
}
32+
}
33+
34+
return $qs ? substr($qs, 0, -1) : '';
35+
}
36+
}

src/Request.php

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use AsyncAws\Core\Exception\InvalidArgument;
66
use AsyncAws\Core\Exception\LogicException;
7+
use AsyncAws\Core\HttpClient\BuildHttpQueryTrait;
78
use AsyncAws\Core\Stream\RequestStream;
89

910
/**
@@ -13,6 +14,8 @@
1314
*/
1415
final class Request
1516
{
17+
use BuildHttpQueryTrait;
18+
1619
/**
1720
* @var string
1821
*/
@@ -39,7 +42,7 @@ final class Request
3942
private $queryString;
4043

4144
/**
42-
* @var array<string, string>
45+
* @var array<string, string|string[]>
4346
*/
4447
private $query;
4548

@@ -59,8 +62,8 @@ final class Request
5962
private $parsed;
6063

6164
/**
62-
* @param array<string, string> $query
63-
* @param array<string, string> $headers
65+
* @param array<string, string|string[]> $query
66+
* @param array<string, string> $headers
6467
*/
6568
public function __construct(string $method, string $uri, array $query, array $headers, RequestStream $body, string $hostPrefix = '')
6669
{
@@ -141,20 +144,26 @@ public function removeQueryAttribute(string $name): void
141144
$this->endpoint = '';
142145
}
143146

144-
public function setQueryAttribute(string $name, string $value): void
147+
/**
148+
* @param string|string[] $value
149+
*/
150+
public function setQueryAttribute(string $name, string|array $value): void
145151
{
146152
$this->query[$name] = $value;
147153
$this->queryString = null;
148154
$this->endpoint = '';
149155
}
150156

151-
public function getQueryAttribute(string $name): ?string
157+
/**
158+
* @return string|string[]|null
159+
*/
160+
public function getQueryAttribute(string $name): string|array|null
152161
{
153162
return $this->query[$name] ?? null;
154163
}
155164

156165
/**
157-
* @return array<string, string>
166+
* @return array<string, string|string[]>
158167
*/
159168
public function getQuery(): array
160169
{
@@ -207,7 +216,7 @@ public function setEndpoint(string $endpoint): void
207216
private function getQueryString(): string
208217
{
209218
if (null === $this->queryString) {
210-
$this->queryString = http_build_query($this->query, '', '&', \PHP_QUERY_RFC3986);
219+
$this->queryString = $this->buildHttpQuery($this->query);
211220
}
212221

213222
return $this->queryString;

0 commit comments

Comments
 (0)