diff -pruN 1.25.0-1/CHANGELOG.md 1.27.1-1/CHANGELOG.md
--- 1.25.0-1/CHANGELOG.md	2025-03-05 20:41:02.000000000 +0000
+++ 1.27.1-1/CHANGELOG.md	2025-09-08 07:05:54.000000000 +0000
@@ -2,6 +2,33 @@
 
 ## NOT RELEASED
 
+## 1.27.1
+
+### Fixed
+
+- SignerV4: fix sort of query parameters to build correct canoncal query string 
+
+## 1.27.0
+
+### Added
+
+- Support for Symfony 8
+
+### Changed
+
+- `ResultMockFactory` does not call `ReflectionProperty::setAccessible()` on PHP 8.1+
+
+## 1.26.0
+
+### Added
+
+- AWS api-change: Added `eu-isoe-west-1` region
+
+### Changed
+
+- Normalize the composer requirements
+- Sort exception alphabetically.
+
 ## 1.25.0
 
 ### Added
diff -pruN 1.25.0-1/composer.json 1.27.1-1/composer.json
--- 1.25.0-1/composer.json	2025-03-05 20:41:02.000000000 +0000
+++ 1.27.1-1/composer.json	2025-09-08 07:05:54.000000000 +0000
@@ -12,13 +12,13 @@
     ],
     "require": {
         "php": "^7.2.5 || ^8.0",
-        "ext-SimpleXML": "*",
         "ext-hash": "*",
         "ext-json": "*",
+        "ext-simplexml": "*",
         "psr/cache": "^1.0 || ^2.0 || ^3.0",
         "psr/log": "^1.0 || ^2.0 || ^3.0",
         "symfony/deprecation-contracts": "^2.1 || ^3.0",
-        "symfony/http-client": "^4.4.16 || ^5.1.7 || ^6.0 || ^7.0",
+        "symfony/http-client": "^4.4.16 || ^5.1.7 || ^6.0 || ^7.0 || ^8.0",
         "symfony/http-client-contracts": "^1.1.8 || ^2.0 || ^3.0",
         "symfony/service-contracts": "^1.0 || ^2.0 || ^3.0"
     },
@@ -38,7 +38,7 @@
     },
     "extra": {
         "branch-alias": {
-            "dev-master": "1.25-dev"
+            "dev-master": "1.27-dev"
         }
     }
 }
diff -pruN 1.25.0-1/debian/changelog 1.27.1-1/debian/changelog
--- 1.25.0-1/debian/changelog	2025-03-08 15:30:10.000000000 +0000
+++ 1.27.1-1/debian/changelog	2025-09-09 05:52:40.000000000 +0000
@@ -1,3 +1,48 @@
+php-async-aws-core (1.27.1-1) unstable; urgency=medium
+
+  [ DmytroVyshnevsky1 ]
+  * fix query params sorting to build correct canonical query string (#1938)
+
+  [ Jérémy Derussé ]
+  * prepare next release
+
+ -- David Prévot <taffit@debian.org>  Tue, 09 Sep 2025 07:52:40 +0200
+
+php-async-aws-core (1.27.0-2) unstable; urgency=medium
+
+  * Fix warning with recent PHPUnit
+  * Remove Rules-Requires-Root
+
+ -- David Prévot <taffit@debian.org>  Sun, 24 Aug 2025 10:44:50 +0200
+
+php-async-aws-core (1.27.0-1) unstable; urgency=medium
+
+  * Upload to unstable now that trixie has been released
+
+  [ Nicolas Grekas ]
+  * Allow Symfony 8 (#1929)
+
+  [ Christian Flothmann ]
+  * do not call setAccessible() on PHP 8.1+ (#1931)
+
+  [ Jérémy Derussé ]
+  * prepare next release (#1932)
+
+ -- David Prévot <taffit@debian.org>  Tue, 12 Aug 2025 11:57:45 +0200
+
+php-async-aws-core (1.26.0-1) experimental; urgency=medium
+
+  * Upload to experimental during the freeze
+
+  [ Jérémy Derussé ]
+  * Sort exceptions alphabetically (#1875)
+  * Prepeare release
+
+  [ Christophe Coevoet ]
+  * Normalize the case of the SimpleXML requirement (#1881)
+
+ -- David Prévot <taffit@debian.org>  Mon, 12 May 2025 18:42:07 +0200
+
 php-async-aws-core (1.25.0-1) unstable; urgency=medium
 
   [ victor-upmeet ]
diff -pruN 1.25.0-1/debian/control 1.27.1-1/debian/control
--- 1.25.0-1/debian/control	2025-03-08 15:30:10.000000000 +0000
+++ 1.27.1-1/debian/control	2025-09-09 05:50:24.000000000 +0000
@@ -17,7 +17,6 @@ Standards-Version: 4.7.2
 Vcs-Git: https://salsa.debian.org/php-team/pear/php-async-aws-core.git
 Vcs-Browser: https://salsa.debian.org/php-team/pear/php-async-aws-core
 Homepage: https://async-aws.com/
-Rules-Requires-Root: no
 
 Package: php-async-aws-core
 Architecture: all
diff -pruN 1.25.0-1/debian/patches/0002-Make-provider-functions-static-PHPUnit-11-Fix.patch 1.27.1-1/debian/patches/0002-Make-provider-functions-static-PHPUnit-11-Fix.patch
--- 1.25.0-1/debian/patches/0002-Make-provider-functions-static-PHPUnit-11-Fix.patch	2025-03-08 15:28:55.000000000 +0000
+++ 1.27.1-1/debian/patches/0002-Make-provider-functions-static-PHPUnit-11-Fix.patch	2025-09-09 05:52:40.000000000 +0000
@@ -6,14 +6,13 @@ Bug-Debian: https://bugs.debian.org/1070
 ---
  tests/HttpClient/AwsRetryStrategyTest.php  | 2 +-
  tests/Unit/ConfigurationTest.php           | 2 +-
- tests/Unit/Signer/SignerV4Test.php         | 2 +-
  tests/Unit/Stream/CallableStreamTest.php   | 6 +++---
  tests/Unit/Stream/FixedSizeStreamTest.php  | 6 +++---
  tests/Unit/Stream/IterableStreamTest.php   | 6 +++---
  tests/Unit/Stream/ResourceStreamTest.php   | 6 +++---
  tests/Unit/Stream/RewindableStreamTest.php | 6 +++---
  tests/Unit/Stream/StringStreamTest.php     | 6 +++---
- 9 files changed, 21 insertions(+), 21 deletions(-)
+ 8 files changed, 20 insertions(+), 20 deletions(-)
 
 diff --git a/tests/HttpClient/AwsRetryStrategyTest.php b/tests/HttpClient/AwsRetryStrategyTest.php
 index a242b23..bccae03 100644
@@ -41,19 +40,6 @@ index e076a82..c5b96ca 100644
      {
          yield 'simple config' => [['endpoint' => 'foo'], [], ['endpoint' => 'foo']];
          yield 'empty config' => [['endpoint' => ''], [], ['endpoint' => '']];
-diff --git a/tests/Unit/Signer/SignerV4Test.php b/tests/Unit/Signer/SignerV4Test.php
-index 495dfb7..fe42964 100644
---- a/tests/Unit/Signer/SignerV4Test.php
-+++ b/tests/Unit/Signer/SignerV4Test.php
-@@ -78,7 +78,7 @@ class SignerV4Test extends TestCase
-         self::assertEquals($expected, $request);
-     }
- 
--    public function provideRequests()
-+    public static function provideRequests()
-     {
-         return [
-             // POST headers should be signed.
 diff --git a/tests/Unit/Stream/CallableStreamTest.php b/tests/Unit/Stream/CallableStreamTest.php
 index fb14d53..dcfce89 100644
 --- a/tests/Unit/Stream/CallableStreamTest.php
diff -pruN 1.25.0-1/debian/patches/0003-Compatibility-with-recent-PHPUnit-12.patch 1.27.1-1/debian/patches/0003-Compatibility-with-recent-PHPUnit-12.patch
--- 1.25.0-1/debian/patches/0003-Compatibility-with-recent-PHPUnit-12.patch	2025-03-08 15:28:55.000000000 +0000
+++ 1.27.1-1/debian/patches/0003-Compatibility-with-recent-PHPUnit-12.patch	2025-09-09 05:52:40.000000000 +0000
@@ -5,14 +5,14 @@ Subject: Compatibility with recent PHPUn
 ---
  tests/HttpClient/AwsRetryStrategyTest.php  | 2 ++
  tests/Unit/ConfigurationTest.php           | 2 ++
- tests/Unit/Signer/SignerV4Test.php         | 2 ++
+ tests/Unit/Signer/SignerV4Test.php         | 4 +++-
  tests/Unit/Stream/CallableStreamTest.php   | 4 ++++
  tests/Unit/Stream/FixedSizeStreamTest.php  | 5 +++++
  tests/Unit/Stream/IterableStreamTest.php   | 4 ++++
  tests/Unit/Stream/ResourceStreamTest.php   | 4 ++++
  tests/Unit/Stream/RewindableStreamTest.php | 4 ++++
  tests/Unit/Stream/StringStreamTest.php     | 4 ++++
- 9 files changed, 31 insertions(+)
+ 9 files changed, 32 insertions(+), 1 deletion(-)
 
 diff --git a/tests/HttpClient/AwsRetryStrategyTest.php b/tests/HttpClient/AwsRetryStrategyTest.php
 index bccae03..0315729 100644
@@ -55,7 +55,7 @@ index c5b96ca..90fb5b1 100644
      {
          foreach ($env as $key => $value) {
 diff --git a/tests/Unit/Signer/SignerV4Test.php b/tests/Unit/Signer/SignerV4Test.php
-index fe42964..1a4b1b8 100644
+index 18acb93..328beb3 100644
 --- a/tests/Unit/Signer/SignerV4Test.php
 +++ b/tests/Unit/Signer/SignerV4Test.php
 @@ -9,6 +9,7 @@ use AsyncAws\Core\Request;
@@ -74,6 +74,22 @@ index fe42964..1a4b1b8 100644
      public function testSignsRequests($rawRequest, $rawExpected)
      {
          $request = $this->parseRequest($rawRequest);
+@@ -130,7 +132,6 @@ class SignerV4Test extends TestCase
+             [
+                 "POST / HTTP/1.1\r\nHost: host.foo.com:443\r\nContent-Length: 4\r\n\r\nTest",
+                 "POST / HTTP/1.1\r\nHost: host.foo.com:443\r\nContent-Length: 4\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=e971be49c79358595ef6214f683ac9c0489d397a5d5d13b361291e751deeca03\r\n\r\nTest",
+-                "POST\n/\n\nhost:host.foo.com:443\n\nhost\n532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25",
+             ],
+             // DateHeader should be kept
+             [
+@@ -143,6 +144,7 @@ class SignerV4Test extends TestCase
+     /**
+      * @dataProvider provideRequestsWithQueryParams
+      */
++    #[DataProvider('provideRequestsWithQueryParams')]
+     public function testSignsRequestsWithArrayInQueryParams($rawRequestWithoutQuery, $rawExpected, $queryParams)
+     {
+         $request = $this->parseRequest($rawRequestWithoutQuery, $queryParams);
 diff --git a/tests/Unit/Stream/CallableStreamTest.php b/tests/Unit/Stream/CallableStreamTest.php
 index dcfce89..0c5af79 100644
 --- a/tests/Unit/Stream/CallableStreamTest.php
diff -pruN 1.25.0-1/debian/tests/control 1.27.1-1/debian/tests/control
--- 1.25.0-1/debian/tests/control	2024-07-06 11:14:51.000000000 +0000
+++ 1.27.1-1/debian/tests/control	2025-09-09 05:52:40.000000000 +0000
@@ -1,3 +1,3 @@
-Restrictions: rw-build-tree, allow-stderr
+Restrictions: allow-stderr, rw-build-tree
 Depends: phpab, phpunit, pkg-php-tools, @
 Test-Command: mkdir -p vendor && phpabtpl --require async-aws/core > debian/autoload.tests.php.tpl && phpab -o vendor/autoload.php -t debian/autoload.tests.php.tpl tests && phpunit --exclude-group network
diff -pruN 1.25.0-1/phpunit.xml.dist 1.27.1-1/phpunit.xml.dist
--- 1.25.0-1/phpunit.xml.dist	2025-03-05 20:41:02.000000000 +0000
+++ 1.27.1-1/phpunit.xml.dist	2025-09-08 07:05:54.000000000 +0000
@@ -1,17 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
-         backupGlobals="false"
-         colors="true"
-         bootstrap="vendor/autoload.php"
-         failOnRisky="true"
-         failOnWarning="true"
->
-  <coverage>
-    <include>
-      <directory>./src</directory>
-    </include>
-  </coverage>
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" backupGlobals="false" colors="true" bootstrap="vendor/autoload.php" failOnRisky="true" failOnWarning="true">
   <php>
     <ini name="error_reporting" value="-1"/>
   </php>
@@ -20,4 +8,9 @@
       <directory>./tests/</directory>
     </testsuite>
   </testsuites>
+  <source>
+    <include>
+      <directory>./src</directory>
+    </include>
+  </source>
 </phpunit>
diff -pruN 1.25.0-1/src/Signer/SignerV4.php 1.27.1-1/src/Signer/SignerV4.php
--- 1.25.0-1/src/Signer/SignerV4.php	2025-03-05 20:41:02.000000000 +0000
+++ 1.27.1-1/src/Signer/SignerV4.php	2025-09-08 07:05:54.000000000 +0000
@@ -321,7 +321,9 @@ class SignerV4 implements Signer
             return '';
         }
 
-        ksort($query);
+        uksort($query, static function (string $a, string $b): int {
+            return strcmp(rawurlencode($a), rawurlencode($b));
+        });
         $encodedQuery = [];
         foreach ($query as $key => $values) {
             if (!\is_array($values)) {
diff -pruN 1.25.0-1/src/Sts/StsClient.php 1.27.1-1/src/Sts/StsClient.php
--- 1.25.0-1/src/Sts/StsClient.php	2025-03-05 20:41:02.000000000 +0000
+++ 1.27.1-1/src/Sts/StsClient.php	2025-09-08 07:05:54.000000000 +0000
@@ -125,19 +125,19 @@ class StsClient extends AbstractApi
      *   '@region'?: string|null,
      * }|AssumeRoleRequest $input
      *
+     * @throws ExpiredTokenException
      * @throws MalformedPolicyDocumentException
      * @throws PackedPolicyTooLargeException
      * @throws RegionDisabledException
-     * @throws ExpiredTokenException
      */
     public function assumeRole($input): AssumeRoleResponse
     {
         $input = AssumeRoleRequest::create($input);
         $response = $this->getResponse($input->request(), new RequestContext(['operation' => 'AssumeRole', 'region' => $input->getRegion(), 'exceptionMapping' => [
+            'ExpiredTokenException' => ExpiredTokenException::class,
             'MalformedPolicyDocument' => MalformedPolicyDocumentException::class,
             'PackedPolicyTooLarge' => PackedPolicyTooLargeException::class,
             'RegionDisabledException' => RegionDisabledException::class,
-            'ExpiredTokenException' => ExpiredTokenException::class,
         ]]));
 
         return new AssumeRoleResponse($response);
@@ -273,24 +273,24 @@ class StsClient extends AbstractApi
      *   '@region'?: string|null,
      * }|AssumeRoleWithWebIdentityRequest $input
      *
-     * @throws MalformedPolicyDocumentException
-     * @throws PackedPolicyTooLargeException
-     * @throws IDPRejectedClaimException
+     * @throws ExpiredTokenException
      * @throws IDPCommunicationErrorException
+     * @throws IDPRejectedClaimException
      * @throws InvalidIdentityTokenException
-     * @throws ExpiredTokenException
+     * @throws MalformedPolicyDocumentException
+     * @throws PackedPolicyTooLargeException
      * @throws RegionDisabledException
      */
     public function assumeRoleWithWebIdentity($input): AssumeRoleWithWebIdentityResponse
     {
         $input = AssumeRoleWithWebIdentityRequest::create($input);
         $response = $this->getResponse($input->request(), new RequestContext(['operation' => 'AssumeRoleWithWebIdentity', 'region' => $input->getRegion(), 'exceptionMapping' => [
-            'MalformedPolicyDocument' => MalformedPolicyDocumentException::class,
-            'PackedPolicyTooLarge' => PackedPolicyTooLargeException::class,
-            'IDPRejectedClaim' => IDPRejectedClaimException::class,
+            'ExpiredTokenException' => ExpiredTokenException::class,
             'IDPCommunicationError' => IDPCommunicationErrorException::class,
+            'IDPRejectedClaim' => IDPRejectedClaimException::class,
             'InvalidIdentityToken' => InvalidIdentityTokenException::class,
-            'ExpiredTokenException' => ExpiredTokenException::class,
+            'MalformedPolicyDocument' => MalformedPolicyDocumentException::class,
+            'PackedPolicyTooLarge' => PackedPolicyTooLargeException::class,
             'RegionDisabledException' => RegionDisabledException::class,
         ]]));
 
@@ -405,6 +405,13 @@ class StsClient extends AbstractApi
                     'signService' => 'sts',
                     'signVersions' => ['v4'],
                 ];
+            case 'eu-isoe-west-1':
+                return [
+                    'endpoint' => 'https://sts.eu-isoe-west-1.cloud.adc-e.uk',
+                    'signRegion' => 'eu-isoe-west-1',
+                    'signService' => 'sts',
+                    'signVersions' => ['v4'],
+                ];
             case 'us-isob-east-1':
                 return [
                     'endpoint' => 'https://sts.us-isob-east-1.sc2s.sgov.gov',
diff -pruN 1.25.0-1/src/Test/ResultMockFactory.php 1.27.1-1/src/Test/ResultMockFactory.php
--- 1.25.0-1/src/Test/ResultMockFactory.php	2025-03-05 20:41:02.000000000 +0000
+++ 1.27.1-1/src/Test/ResultMockFactory.php	2025-09-08 07:05:54.000000000 +0000
@@ -84,7 +84,9 @@ class ResultMockFactory
         // Make sure the Result is initialized
         $reflectionClass = new \ReflectionClass(Result::class);
         $initializedProperty = $reflectionClass->getProperty('initialized');
-        $initializedProperty->setAccessible(true);
+        if (\PHP_VERSION_ID < 80100) {
+            $initializedProperty->setAccessible(true);
+        }
 
         /** @psalm-var \ReflectionClass<T> $reflectionClass */
         $reflectionClass = new \ReflectionClass($class);
@@ -116,7 +118,9 @@ class ResultMockFactory
                     $property = $reflectionClass->getProperty($propertyName);
                 }
             }
-            $property->setAccessible(true);
+            if (\PHP_VERSION_ID < 80100) {
+                $property->setAccessible(true);
+            }
             $property->setValue($object, $propertyValue);
         }
 
@@ -151,10 +155,14 @@ class ResultMockFactory
 
         $reflectionClass = new \ReflectionClass(Waiter::class);
         $propertyResponse = $reflectionClass->getProperty('response');
-        $propertyResponse->setAccessible(true);
+        if (\PHP_VERSION_ID < 80100) {
+            $propertyResponse->setAccessible(true);
+        }
 
         $propertyState = $reflectionClass->getProperty('finalState');
-        $propertyState->setAccessible(true);
+        if (\PHP_VERSION_ID < 80100) {
+            $propertyState->setAccessible(true);
+        }
 
         /** @psalm-var \ReflectionClass<T> $reflectionClass */
         $reflectionClass = new \ReflectionClass($class);
@@ -217,7 +225,9 @@ class ResultMockFactory
             }
 
             if (null !== $propertyValue) {
-                $property->setAccessible(true);
+                if (\PHP_VERSION_ID < 80100) {
+                    $property->setAccessible(true);
+                }
                 $property->setValue($object, $propertyValue);
             }
         }
@@ -260,14 +270,18 @@ class ResultMockFactory
         if (class_exists($awsClientClass)) {
             $awsClientMock = (new \ReflectionClass($awsClientClass))->newInstanceWithoutConstructor();
             $property = $reflectionClass->getProperty('awsClient');
-            $property->setAccessible(true);
+            if (\PHP_VERSION_ID < 80100) {
+                $property->setAccessible(true);
+            }
             $property->setValue($object, $awsClientMock);
         }
 
         if (class_exists($inputClass)) {
             $inputMock = (new \ReflectionClass($inputClass))->newInstanceWithoutConstructor();
             $property = $reflectionClass->getProperty('input');
-            $property->setAccessible(true);
+            if (\PHP_VERSION_ID < 80100) {
+                $property->setAccessible(true);
+            }
             $property->setValue($object, $inputMock);
         }
     }
@@ -278,15 +292,21 @@ class ResultMockFactory
         $response = $reflectionClass->newInstanceWithoutConstructor();
 
         $property = $reflectionClass->getProperty('resolveResult');
-        $property->setAccessible(true);
+        if (\PHP_VERSION_ID < 80100) {
+            $property->setAccessible(true);
+        }
         $property->setValue($response, true);
 
         $property = $reflectionClass->getProperty('bodyDownloaded');
-        $property->setAccessible(true);
+        if (\PHP_VERSION_ID < 80100) {
+            $property->setAccessible(true);
+        }
         $property->setValue($response, true);
 
         $property = $reflectionClass->getProperty('httpResponse');
-        $property->setAccessible(true);
+        if (\PHP_VERSION_ID < 80100) {
+            $property->setAccessible(true);
+        }
         $property->setValue($response, new SimpleMockedResponse());
 
         return $response;
diff -pruN 1.25.0-1/tests/Unit/Signer/SignerV4Test.php 1.27.1-1/tests/Unit/Signer/SignerV4Test.php
--- 1.25.0-1/tests/Unit/Signer/SignerV4Test.php	2025-03-05 20:41:02.000000000 +0000
+++ 1.27.1-1/tests/Unit/Signer/SignerV4Test.php	2025-09-08 07:05:54.000000000 +0000
@@ -78,7 +78,7 @@ class SignerV4Test extends TestCase
         self::assertEquals($expected, $request);
     }
 
-    public function provideRequests()
+    public static function provideRequests()
     {
         return [
             // POST headers should be signed.
@@ -140,7 +140,58 @@ class SignerV4Test extends TestCase
         ];
     }
 
-    private function parseRequest(string $req): Request
+    /**
+     * @dataProvider provideRequestsWithQueryParams
+     */
+    public function testSignsRequestsWithArrayInQueryParams($rawRequestWithoutQuery, $rawExpected, $queryParams)
+    {
+        $request = $this->parseRequest($rawRequestWithoutQuery, $queryParams);
+
+        $signer = new SignerV4('host', 'us-east-1');
+        $context = new RequestContext(['currentDate' => new \DateTimeImmutable('20110909T233600Z')]);
+        $credentials = new Credentials('AKIDEXAMPLE', 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY');
+
+        $signer->sign($request, $credentials, $context);
+
+        $expected = $this->parseRequest($rawExpected, $queryParams);
+
+        self::assertEquals($expected, $request);
+    }
+
+    public static function provideRequestsWithQueryParams()
+    {
+        return [
+            // GET Case with array in query params
+            [
+                "GET / HTTP/1.1\r\nHost: host.foo.com:443\r\n\r\n",
+                "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",
+                [
+                    'foos[0]' => '834127',
+                    'foos[1]' => '59',
+                    'foos[2]' => '90123',
+                    'foos[3]' => '4708',
+                    'foos[4]' => '120001',
+                    'foos[5]' => '333',
+                    'foos[6]' => '78005',
+                    'foos[7]' => '2',
+                    'foos[8]' => 'string value',
+                    'foos[9]' => '40617',
+                    'foos[10]' => '715',
+                ],
+            ],
+            // GET Simple case with query params (copy of one of the cases above from testSignsRequests)
+            [
+                "GET / HTTP/1.1\r\nHost: host.foo.com:443\r\n\r\n",
+                "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",
+                [
+                    'a' => 'foo',
+                    'b' => 'foo',
+                ],
+            ],
+        ];
+    }
+
+    private function parseRequest(string $req, array $queryParams = []): Request
     {
         $lines = explode("\r\n", $req);
         [$method, $path] = explode(' ', array_shift($lines));
@@ -156,6 +207,12 @@ class SignerV4Test extends TestCase
 
         $req = new Request($method, '/', [], $headers, StringStream::create(implode("\n", $lines)));
         $req->setEndpoint('https://' . $headers['Host'] . $path);
+
+        // currently the library cannot properly parse query params if they contain arrays, so we need to set them manually
+        foreach ($queryParams as $k => $v) {
+            $req->setQueryAttribute($k, $v);
+        }
+
         // Ensure that the memoized property is filled, so that comparison works consistently.
         $req->getEndpoint();
 
