From b12c8ddee5a35cf1684b2e75c2f8276c1eba9500 Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Fri, 12 Jun 2020 18:22:15 +0200 Subject: [PATCH 1/2] Implement new tests to highlight the issue. --- Tests/Functional/CovertTest.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Tests/Functional/CovertTest.php b/Tests/Functional/CovertTest.php index 11f86c8..3e3b00e 100644 --- a/Tests/Functional/CovertTest.php +++ b/Tests/Functional/CovertTest.php @@ -94,6 +94,7 @@ public function testConvertRequestMultipleTimes($request, $firstFactory, $second $this->assertEquals($request->getMethod(), $finalRequest->getMethod()); $this->assertEquals($request->getRequestTarget(), $finalRequest->getRequestTarget()); $this->assertEquals((string) $request->getUri(), (string) $finalRequest->getUri()); + $this->assertEquals($request->getUri()->getQuery(), $finalRequest->getUri()->getQuery()); $this->assertEquals((string) $request->getBody(), (string) $finalRequest->getBody()); $this->assertEquals($strToLower($request->getHeaders()), $strToLower($finalRequest->getHeaders())); $this->assertEquals($request->getProtocolVersion(), $finalRequest->getProtocolVersion()); @@ -152,10 +153,20 @@ public function requestProvider() $psr17Factory = new PsrHttpFactory($nyholmFactory, $nyholmFactory, $nyholmFactory, $nyholmFactory); $symfonyFactory = new HttpFoundationFactory(); + $psr7ServerRequestWithDots = (new Psr7Request('GET', 'http://localhost/api?foo.bar=foodotbar&foo.led[]=IamNot&foo.led[]=fooled&and another one=please fix me')) + ->withQueryParams([ + 'foo.bar' => 'foodotbar', + 'foo.led' => [ + 'IamNot', + 'fooled', + ], + 'and another one' => 'please fix me', + ]); + return array_merge([ [$sfRequest, $psr17Factory, $symfonyFactory], - ], array_map(function ($psr7Request) use ($symfonyFactory, $psr17Factory) { - return [$psr7Request, $symfonyFactory, $psr17Factory]; + ], array_map(function ($psr7Request) use ($symfonyFactory, $psr17Factory, $psr7ServerRequestWithDots) { + return [$psr7Request, $symfonyFactory, $psr17Factory, $psr7ServerRequestWithDots]; }, $psr7Requests)); } From f4a56c2e07d051d9e363895f114af993e611299b Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Fri, 12 Jun 2020 18:27:49 +0200 Subject: [PATCH 2/2] Handle GET parameters with dots and spaces without altering them. --- Factory/PsrHttpFactory.php | 41 ++++++++++++++++++++++++++++++++- Tests/Functional/CovertTest.php | 2 +- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/Factory/PsrHttpFactory.php b/Factory/PsrHttpFactory.php index dfcfe73..7f36b5c 100644 --- a/Factory/PsrHttpFactory.php +++ b/Factory/PsrHttpFactory.php @@ -72,7 +72,15 @@ public function createRequest(Request $symfonyRequest) $request = $request->withAttribute($key, $value); } - return $request; + $queryString = urldecode($symfonyRequest->server->get('QUERY_STRING', '')); + + return $request + ->withUri( + $request + ->getUri() + ->withQuery($queryString) + ) + ->withQueryParams(iterator_to_array($this->parseStr($queryString))); } /** @@ -165,4 +173,35 @@ public function createResponse(Response $symfonyResponse) return $response; } + + /** + * Custom parse_str() function that doesn't alter the parameters key value. + * + * @return \Generator + */ + private function parseStr(string $queryString): \Generator + { + parse_str( + array_reduce( + ['urldecode', 'bin2hex'], + static function (string $queryString, callable $callback): string { + return (string) preg_replace_callback( + '/(?[^&=]+?)(?:\[[^&=]*\])?=(?[^&=]+)/', + static function (array $match) use ($callback): string { + return str_replace($match['key'], $callback($match['key']), $match[0]); + }, + $queryString + ); + }, + $queryString + ), + $parameters + ); + + foreach ($parameters as $key => $value) { + yield (string) hex2bin($key) => $value; + } + + return yield from []; + } } diff --git a/Tests/Functional/CovertTest.php b/Tests/Functional/CovertTest.php index 3e3b00e..92365c9 100644 --- a/Tests/Functional/CovertTest.php +++ b/Tests/Functional/CovertTest.php @@ -153,7 +153,7 @@ public function requestProvider() $psr17Factory = new PsrHttpFactory($nyholmFactory, $nyholmFactory, $nyholmFactory, $nyholmFactory); $symfonyFactory = new HttpFoundationFactory(); - $psr7ServerRequestWithDots = (new Psr7Request('GET', 'http://localhost/api?foo.bar=foodotbar&foo.led[]=IamNot&foo.led[]=fooled&and another one=please fix me')) + $psr7ServerRequestWithDots = (new Psr7Request('GET', 'http://localhost/api?foo.bar=foodotbar&foo.led[]=IamNot&foo.led[]=fooled&and another one=please fix me')) ->withQueryParams([ 'foo.bar' => 'foodotbar', 'foo.led' => [