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/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/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".']); + } } 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,