From 767fbdd84d93dae59bc11037b684c5ad7cb06e9e Mon Sep 17 00:00:00 2001 From: soyuka Date: Thu, 15 May 2025 08:09:39 +0200 Subject: [PATCH 1/2] fix: reset format when an error occurs --- src/Symfony/EventListener/ErrorListener.php | 5 +++-- .../ApiResource/XmlWithJsonError.php | 21 +++++++++++++++++++ tests/Functional/ErrorTest.php | 14 ++++++++++++- 3 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 tests/Fixtures/TestBundle/ApiResource/XmlWithJsonError.php diff --git a/src/Symfony/EventListener/ErrorListener.php b/src/Symfony/EventListener/ErrorListener.php index 19e5593a3ca..f973403cf92 100644 --- a/src/Symfony/EventListener/ErrorListener.php +++ b/src/Symfony/EventListener/ErrorListener.php @@ -68,8 +68,9 @@ public function __construct( protected function duplicateRequest(\Throwable $exception, Request $request): Request { $format = $this->getRequestFormat($request, $this->errorFormats, false); - // Because ErrorFormatGuesser is buggy in some cases - $request->setRequestFormat($format); + // Reset the request format as it may be that the original request format negotiation won't have the same result + // when an error occurs + $request->setRequestFormat(null); $apiOperation = $this->initializeOperation($request); // TODO: add configuration flag to: diff --git a/tests/Fixtures/TestBundle/ApiResource/XmlWithJsonError.php b/tests/Fixtures/TestBundle/ApiResource/XmlWithJsonError.php new file mode 100644 index 00000000000..d68359bc95c --- /dev/null +++ b/tests/Fixtures/TestBundle/ApiResource/XmlWithJsonError.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource; + +use ApiPlatform\Metadata\Post; + +#[Post(inputFormats: ['xml' => 'application/xml'], uriVariables: ['id'])] +class XmlWithJsonError +{ +} diff --git a/tests/Functional/ErrorTest.php b/tests/Functional/ErrorTest.php index 99c10f1b329..7893b1e9241 100644 --- a/tests/Functional/ErrorTest.php +++ b/tests/Functional/ErrorTest.php @@ -15,6 +15,7 @@ use ApiPlatform\State\ApiResource\Error; use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; +use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\XmlWithJsonError; use ApiPlatform\Tests\SetupClassResourcesTrait; use PHPUnit\Framework\Attributes\DataProvider; @@ -29,7 +30,7 @@ final class ErrorTest extends ApiTestCase */ public static function getResources(): array { - return [Error::class]; + return [Error::class, XmlWithJsonError::class]; } #[DataProvider('formatsProvider')] @@ -79,4 +80,15 @@ public static function formatsProvider(): array ], ]; } + + public function testJsonError(): void + { + self::createClient()->request('POST', '/xml_with_json_errors', [ + 'headers' => ['content-type' => 'application/json'], + 'body' => '', + ]); + + $this->assertResponseStatusCodeSame(415); + $this->assertJsonContains(['detail' => 'The content-type "application/json" is not supported. Supported MIME types are "application/xml".']); + } } From 81dc6bc004ae0a8bb78fef43659c28cde29ad161 Mon Sep 17 00:00:00 2001 From: soyuka Date: Thu, 15 May 2025 08:10:42 +0200 Subject: [PATCH 2/2] fix(symfony): allow route default _format configuration --- src/Symfony/Routing/ApiLoader.php | 3 +-- tests/Symfony/Routing/ApiLoaderTest.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Routing/ApiLoader.php b/src/Symfony/Routing/ApiLoader.php index 6da29ed7750..ba60d580e5f 100644 --- a/src/Symfony/Routing/ApiLoader.php +++ b/src/Symfony/Routing/ApiLoader.php @@ -90,11 +90,10 @@ public function load(mixed $data, ?string $type = null): RouteCollection $path, [ '_controller' => $controller ?? 'api_platform.action.placeholder', - '_format' => null, '_stateless' => $operation->getStateless(), '_api_resource_class' => $resourceClass, '_api_operation_name' => $operationName, - ] + ($operation->getDefaults() ?? []), + ] + ($operation->getDefaults() ?? []) + ['_format' => null], $operation->getRequirements() ?? [], $operation->getOptions() ?? [], $operation->getHost() ?? '', diff --git a/tests/Symfony/Routing/ApiLoaderTest.php b/tests/Symfony/Routing/ApiLoaderTest.php index 6766527825f..f71cf2f33d8 100644 --- a/tests/Symfony/Routing/ApiLoaderTest.php +++ b/tests/Symfony/Routing/ApiLoaderTest.php @@ -321,7 +321,7 @@ private function getRoute(string $path, string $controller, ?bool $stateless, st $path, [ '_controller' => $controller, - '_format' => null, + '_format' => $extraDefaults['_format'] ?? null, '_stateless' => $stateless, '_api_resource_class' => $resourceClass, '_api_operation_name' => $operationName,