@@ -78,7 +78,7 @@ public function testSignsRequests($rawRequest, $rawExpected)
7878 self ::assertEquals ($ expected , $ request );
7979 }
8080
81- public function provideRequests ()
81+ public static function provideRequests ()
8282 {
8383 return [
8484 // POST headers should be signed.
@@ -140,7 +140,58 @@ public function provideRequests()
140140 ];
141141 }
142142
143- private function parseRequest (string $ req ): Request
143+ /**
144+ * @dataProvider provideRequestsWithQueryParams
145+ */
146+ public function testSignsRequestsWithArrayInQueryParams ($ rawRequestWithoutQuery , $ rawExpected , $ queryParams )
147+ {
148+ $ request = $ this ->parseRequest ($ rawRequestWithoutQuery , $ queryParams );
149+
150+ $ signer = new SignerV4 ('host ' , 'us-east-1 ' );
151+ $ context = new RequestContext (['currentDate ' => new \DateTimeImmutable ('20110909T233600Z ' )]);
152+ $ credentials = new Credentials ('AKIDEXAMPLE ' , 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY ' );
153+
154+ $ signer ->sign ($ request , $ credentials , $ context );
155+
156+ $ expected = $ this ->parseRequest ($ rawExpected , $ queryParams );
157+
158+ self ::assertEquals ($ expected , $ request );
159+ }
160+
161+ public static function provideRequestsWithQueryParams ()
162+ {
163+ return [
164+ // GET Case with array in query params
165+ [
166+ "GET / HTTP/1.1 \r\nHost: host.foo.com:443 \r\n\r\n" ,
167+ "GET / HTTP/1.1 \r\nHost: host.foo.com:443 \r\nX-Amz-Date: 20110909T233600Z \r\nAuthorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=host;x-amz-date, Signature=7bd9c6fed0473be1f7ea96ff34c7d79e71a92932054a24b4210b3a56e4ab46d3 \r\n\r\n" ,
168+ [
169+ 'foos[0] ' => '834127 ' ,
170+ 'foos[1] ' => '59 ' ,
171+ 'foos[2] ' => '90123 ' ,
172+ 'foos[3] ' => '4708 ' ,
173+ 'foos[4] ' => '120001 ' ,
174+ 'foos[5] ' => '333 ' ,
175+ 'foos[6] ' => '78005 ' ,
176+ 'foos[7] ' => '2 ' ,
177+ 'foos[8] ' => 'string value ' ,
178+ 'foos[9] ' => '40617 ' ,
179+ 'foos[10] ' => '715 ' ,
180+ ],
181+ ],
182+ // GET Simple case with query params (copy of one of the cases above from testSignsRequests)
183+ [
184+ "GET / HTTP/1.1 \r\nHost: host.foo.com:443 \r\n\r\n" ,
185+ "GET / HTTP/1.1 \r\nHost: host.foo.com:443 \r\nX-Amz-Date: 20110909T233600Z \r\nAuthorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=host;x-amz-date, Signature=1c3274381ae12d8817336268d7da17672bd57e7348e39b7b9c567280f73742af \r\n\r\n" ,
186+ [
187+ 'a ' => 'foo ' ,
188+ 'b ' => 'foo ' ,
189+ ],
190+ ],
191+ ];
192+ }
193+
194+ private function parseRequest (string $ req , array $ queryParams = []): Request
144195 {
145196 $ lines = explode ("\r\n" , $ req );
146197 [$ method , $ path ] = explode (' ' , array_shift ($ lines ));
@@ -156,6 +207,12 @@ private function parseRequest(string $req): Request
156207
157208 $ req = new Request ($ method , '/ ' , [], $ headers , StringStream::create (implode ("\n" , $ lines )));
158209 $ req ->setEndpoint ('https:// ' . $ headers ['Host ' ] . $ path );
210+
211+ // currently the library cannot properly parse query params if they contain arrays, so we need to set them manually
212+ foreach ($ queryParams as $ k => $ v ) {
213+ $ req ->setQueryAttribute ($ k , $ v );
214+ }
215+
159216 // Ensure that the memoized property is filled, so that comparison works consistently.
160217 $ req ->getEndpoint ();
161218
0 commit comments