From 3a8caad62dfc301ad8c32adb778e859f6896c487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Pillevesse?= Date: Fri, 21 Jul 2023 14:42:44 +0200 Subject: [PATCH] Leverage `Request::getPayload()` to populate the parsed body of PSR-7 requests --- Factory/PsrHttpFactory.php | 20 +++++++++++- Tests/Factory/PsrHttpFactoryTest.php | 49 ++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/Factory/PsrHttpFactory.php b/Factory/PsrHttpFactory.php index b1b6f9a..1c98e7b 100644 --- a/Factory/PsrHttpFactory.php +++ b/Factory/PsrHttpFactory.php @@ -18,6 +18,7 @@ use Psr\Http\Message\UploadedFileInterface; use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface; use Symfony\Component\HttpFoundation\BinaryFileResponse; +use Symfony\Component\HttpFoundation\Exception\JsonException; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -27,6 +28,7 @@ * Builds Psr\HttpMessage instances using a PSR-17 implementation. * * @author Antonio J. García Lagar + * @author Aurélien Pillevesse */ class PsrHttpFactory implements HttpMessageFactoryInterface { @@ -67,12 +69,28 @@ public function createRequest(Request $symfonyRequest) $body = $this->streamFactory->createStreamFromResource($symfonyRequest->getContent(true)); + if (method_exists(Request::class, 'getContentTypeFormat')) { + $format = $symfonyRequest->getContentTypeFormat(); + } else { + $format = $symfonyRequest->getContentType(); + } + + if (method_exists(Request::class, 'getPayload') && 'json' === $format) { + try { + $parsedBody = $symfonyRequest->getPayload()->all(); + } catch (JsonException $e) { + $parsedBody = []; + } + } else { + $parsedBody = $symfonyRequest->request->all(); + } + $request = $request ->withBody($body) ->withUploadedFiles($this->getFiles($symfonyRequest->files->all())) ->withCookieParams($symfonyRequest->cookies->all()) ->withQueryParams($symfonyRequest->query->all()) - ->withParsedBody($symfonyRequest->request->all()) + ->withParsedBody($parsedBody) ; foreach ($symfonyRequest->attributes->all() as $key => $value) { diff --git a/Tests/Factory/PsrHttpFactoryTest.php b/Tests/Factory/PsrHttpFactoryTest.php index a1cd1b1..adc4368 100644 --- a/Tests/Factory/PsrHttpFactoryTest.php +++ b/Tests/Factory/PsrHttpFactoryTest.php @@ -25,6 +25,7 @@ /** * @author Kévin Dunglas * @author Antonio J. García Lagar + * @author Aurélien Pillevesse */ class PsrHttpFactoryTest extends TestCase { @@ -243,4 +244,52 @@ public function testUploadErrNoFile() $this->assertSame(\UPLOAD_ERR_NO_FILE, $uploadedFiles['f1']->getError()); $this->assertSame(\UPLOAD_ERR_NO_FILE, $uploadedFiles['f2']->getError()); } + + public function testJsonContent() + { + if (!method_exists(Request::class, 'getPayload')) { + $this->markTestSkipped(); + } + + $headers = [ + 'HTTP_HOST' => 'http_host.fr', + 'CONTENT_TYPE' => 'application/json', + ]; + $request = new Request([], [], [], [], [], $headers, '{"city":"Paris","country":"France"}'); + $psrRequest = $this->factory->createRequest($request); + + $this->assertSame(['city' => 'Paris', 'country' => 'France'], $psrRequest->getParsedBody()); + } + + public function testEmptyJsonContent() + { + if (!method_exists(Request::class, 'getPayload')) { + $this->markTestSkipped(); + } + + $headers = [ + 'HTTP_HOST' => 'http_host.fr', + 'CONTENT_TYPE' => 'application/json', + ]; + $request = new Request([], [], [], [], [], $headers, '{}'); + $psrRequest = $this->factory->createRequest($request); + + $this->assertSame([], $psrRequest->getParsedBody()); + } + + public function testWrongJsonContent() + { + if (!method_exists(Request::class, 'getPayload')) { + $this->markTestSkipped(); + } + + $headers = [ + 'HTTP_HOST' => 'http_host.fr', + 'CONTENT_TYPE' => 'application/json', + ]; + $request = new Request([], [], [], [], [], $headers, '{"city":"Paris"'); + $psrRequest = $this->factory->createRequest($request); + + $this->assertSame([], $psrRequest->getParsedBody()); + } }