diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 22517ad5c7d3f..9d80f497b2c89 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -452,6 +452,7 @@ public function load(array $configs, ContainerBuilder $container) $this->registerSecretsConfiguration($config['secrets'], $container, $loader); $container->getDefinition('exception_listener')->replaceArgument(3, $config['exceptions']); + $container->getDefinition('error_handler.error_renderer.html')->replaceArgument(6, $config['exceptions']); if ($this->isConfigEnabled($container, $config['serializer'])) { if (!class_exists(\Symfony\Component\Serializer\Serializer::class)) { @@ -459,6 +460,8 @@ public function load(array $configs, ContainerBuilder $container) } $this->registerSerializerConfiguration($config['serializer'], $container, $loader); + + $container->getDefinition('error_handler.error_renderer.serializer')->replaceArgument(4, $config['exceptions']); } if ($propertyInfoEnabled) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/error_renderer.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/error_renderer.php index 67f28ce44d838..abc0c67e60cff 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/error_renderer.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/error_renderer.php @@ -30,6 +30,7 @@ ->factory([HtmlErrorRenderer::class, 'getAndCleanOutputBuffer']) ->args([service('request_stack')]), service('logger')->nullOnInvalid(), + abstract_arg('Configuration per exception class'), ]) ->alias('error_renderer.html', 'error_handler.error_renderer.html') diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php index dfb2589cba315..0176f8677b75f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php @@ -208,6 +208,7 @@ inline_service() ->factory([HtmlErrorRenderer::class, 'isDebug']) ->args([service('request_stack'), param('kernel.debug')]), + abstract_arg('Configuration per exception class'), ]) ; diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php index 00b8d8aafbd5a..0b96a819e3e51 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php @@ -106,7 +106,7 @@ param('kernel.error_controller'), service('logger')->nullOnInvalid(), param('kernel.debug'), - abstract_arg('an exceptions to log & status code mapping'), + abstract_arg('Configuration per exception class'), ]) ->tag('kernel.event_subscriber') ->tag('monolog.logger', ['channel' => 'request']) diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 71e4940ff0a4b..eb57788da90cc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -23,7 +23,7 @@ "symfony/dependency-injection": "^5.3|^6.0", "symfony/deprecation-contracts": "^2.1|^3", "symfony/event-dispatcher": "^5.1|^6.0", - "symfony/error-handler": "^4.4.1|^5.0.1|^6.0", + "symfony/error-handler": "^5.4.2|^6.0.2", "symfony/http-foundation": "^5.3|^6.0", "symfony/http-kernel": "^5.4|^6.0", "symfony/polyfill-mbstring": "~1.0", diff --git a/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php b/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php index 6f12185a068ca..a12149f369579 100644 --- a/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php +++ b/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php @@ -39,15 +39,17 @@ class HtmlErrorRenderer implements ErrorRendererInterface private $projectDir; private $outputBuffer; private $logger; + private $exceptionsMapping; private static $template = 'views/error.html.php'; /** - * @param bool|callable $debug The debugging mode as a boolean or a callable that should return it + * @param bool|callable $debug The debugging mode as a boolean or a callable that should return it * @param string|FileLinkFormatter|null $fileLinkFormat - * @param bool|callable $outputBuffer The output buffer as a string or a callable that should return it + * @param bool|callable $outputBuffer The output buffer as a string or a callable that should return it + * @param array $exceptionsMapping Configuration per exception class */ - public function __construct($debug = false, string $charset = null, $fileLinkFormat = null, string $projectDir = null, $outputBuffer = '', LoggerInterface $logger = null) + public function __construct($debug = false, string $charset = null, $fileLinkFormat = null, string $projectDir = null, $outputBuffer = '', LoggerInterface $logger = null, array $exceptionsMapping = []) { if (!\is_bool($debug) && !\is_callable($debug)) { throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a boolean or a callable, "%s" given.', __METHOD__, \gettype($debug))); @@ -63,6 +65,7 @@ public function __construct($debug = false, string $charset = null, $fileLinkFor $this->projectDir = $projectDir; $this->outputBuffer = $outputBuffer; $this->logger = $logger; + $this->exceptionsMapping = $exceptionsMapping; } /** @@ -76,7 +79,14 @@ public function render(\Throwable $exception): FlattenException $headers['X-Debug-Exception-File'] = rawurlencode($exception->getFile()).':'.$exception->getLine(); } - $exception = FlattenException::createFromThrowable($exception, null, $headers); + $statusCode = 500; + foreach ($this->exceptionsMapping as $class => $config) { + if ($exception instanceof $class && $config['status_code']) { + $statusCode = $config['status_code']; + break; + } + } + $exception = FlattenException::createFromThrowable($exception, $statusCode, $headers); return $exception->setAsString($this->renderException($exception)); } @@ -262,8 +272,6 @@ private function formatFile(string $file, int $line, string $text = null): strin * @param string $file A file path * @param int $line The selected line number * @param int $srcContext The number of displayed lines around or -1 for the whole file - * - * @return string */ private function fileExcerpt(string $file, int $line, int $srcContext = 3): string { diff --git a/src/Symfony/Component/ErrorHandler/ErrorRenderer/SerializerErrorRenderer.php b/src/Symfony/Component/ErrorHandler/ErrorRenderer/SerializerErrorRenderer.php index cec8e4d413dce..f49bd3aec94cd 100644 --- a/src/Symfony/Component/ErrorHandler/ErrorRenderer/SerializerErrorRenderer.php +++ b/src/Symfony/Component/ErrorHandler/ErrorRenderer/SerializerErrorRenderer.php @@ -28,13 +28,15 @@ class SerializerErrorRenderer implements ErrorRendererInterface private $format; private $fallbackErrorRenderer; private $debug; + private $exceptionsMapping; /** - * @param string|callable(FlattenException) $format The format as a string or a callable that should return it - * formats not supported by Request::getMimeTypes() should be given as mime types - * @param bool|callable $debug The debugging mode as a boolean or a callable that should return it + * @param string|callable(FlattenException) $format The format as a string or a callable that should return it + * formats not supported by Request::getMimeTypes() should be given as mime types + * @param bool|callable $debug The debugging mode as a boolean or a callable that should return it + * @param array $exceptionsMapping Configuration per exception class */ - public function __construct(SerializerInterface $serializer, $format, ErrorRendererInterface $fallbackErrorRenderer = null, $debug = false) + public function __construct(SerializerInterface $serializer, $format, ErrorRendererInterface $fallbackErrorRenderer = null, $debug = false, array $exceptionsMapping = []) { if (!\is_string($format) && !\is_callable($format)) { throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be a string or a callable, "%s" given.', __METHOD__, \gettype($format))); @@ -48,6 +50,7 @@ public function __construct(SerializerInterface $serializer, $format, ErrorRende $this->format = $format; $this->fallbackErrorRenderer = $fallbackErrorRenderer ?? new HtmlErrorRenderer(); $this->debug = $debug; + $this->exceptionsMapping = $exceptionsMapping; } /** @@ -62,7 +65,15 @@ public function render(\Throwable $exception): FlattenException $headers['X-Debug-Exception-File'] = rawurlencode($exception->getFile()).':'.$exception->getLine(); } - $flattenException = FlattenException::createFromThrowable($exception, null, $headers); + $statusCode = 500; + foreach ($this->exceptionsMapping as $class => $config) { + if ($exception instanceof $class && $config['status_code']) { + $statusCode = $config['status_code']; + break; + } + } + + $flattenException = FlattenException::createFromThrowable($exception, $statusCode, $headers); try { $format = \is_string($this->format) ? $this->format : ($this->format)($flattenException); diff --git a/src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php b/src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php index f292d0f79618f..34ed98faa47b6 100644 --- a/src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php +++ b/src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer; +use Symfony\Component\HttpFoundation\Response; class HtmlErrorRendererTest extends TestCase { @@ -40,6 +41,22 @@ public function getRenderData(): iterable %A
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: