Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 480da75

Browse filesBrowse files
author
Alexey Deriyenko
committed
squashing
1 parent 4e7e429 commit 480da75
Copy full SHA for 480da75

File tree

7 files changed

+164
-11
lines changed
Filter options

7 files changed

+164
-11
lines changed

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,13 +452,16 @@ public function load(array $configs, ContainerBuilder $container)
452452
$this->registerSecretsConfiguration($config['secrets'], $container, $loader);
453453

454454
$container->getDefinition('exception_listener')->replaceArgument(3, $config['exceptions']);
455+
$container->getDefinition('error_handler.error_renderer.html')->replaceArgument(6, $config['exceptions']);
455456

456457
if ($this->isConfigEnabled($container, $config['serializer'])) {
457458
if (!class_exists(\Symfony\Component\Serializer\Serializer::class)) {
458459
throw new LogicException('Serializer support cannot be enabled as the Serializer component is not installed. Try running "composer require symfony/serializer-pack".');
459460
}
460461

461462
$this->registerSerializerConfiguration($config['serializer'], $container, $loader);
463+
464+
$container->getDefinition('error_handler.error_renderer.serializer')->replaceArgument(4, $config['exceptions']);
462465
}
463466

464467
if ($propertyInfoEnabled) {

‎src/Symfony/Bundle/FrameworkBundle/Resources/config/error_renderer.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Resources/config/error_renderer.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
->factory([HtmlErrorRenderer::class, 'getAndCleanOutputBuffer'])
3131
->args([service('request_stack')]),
3232
service('logger')->nullOnInvalid(),
33+
abstract_arg('an exceptions to log & status code mapping'),
3334
])
3435

3536
->alias('error_renderer.html', 'error_handler.error_renderer.html')

‎src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@
208208
inline_service()
209209
->factory([HtmlErrorRenderer::class, 'isDebug'])
210210
->args([service('request_stack'), param('kernel.debug')]),
211+
abstract_arg('an exceptions to log & status code mapping'),
211212
])
212213
;
213214

‎src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php
+14-6Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,17 @@ class HtmlErrorRenderer implements ErrorRendererInterface
3939
private $projectDir;
4040
private $outputBuffer;
4141
private $logger;
42+
private $exceptionsMapping;
4243

4344
private static $template = 'views/error.html.php';
4445

4546
/**
46-
* @param bool|callable $debug The debugging mode as a boolean or a callable that should return it
47+
* @param bool|callable $debug The debugging mode as a boolean or a callable that should return it
4748
* @param string|FileLinkFormatter|null $fileLinkFormat
48-
* @param bool|callable $outputBuffer The output buffer as a string or a callable that should return it
49+
* @param bool|callable $outputBuffer The output buffer as a string or a callable that should return it
50+
* @param array $exceptionsMapping An exceptions to log & status code mapping
4951
*/
50-
public function __construct($debug = false, string $charset = null, $fileLinkFormat = null, string $projectDir = null, $outputBuffer = '', LoggerInterface $logger = null)
52+
public function __construct($debug = false, string $charset = null, $fileLinkFormat = null, string $projectDir = null, $outputBuffer = '', LoggerInterface $logger = null, array $exceptionsMapping = [])
5153
{
5254
if (!\is_bool($debug) && !\is_callable($debug)) {
5355
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
6365
$this->projectDir = $projectDir;
6466
$this->outputBuffer = $outputBuffer;
6567
$this->logger = $logger;
68+
$this->exceptionsMapping = $exceptionsMapping;
6669
}
6770

6871
/**
@@ -76,7 +79,14 @@ public function render(\Throwable $exception): FlattenException
7679
$headers['X-Debug-Exception-File'] = rawurlencode($exception->getFile()).':'.$exception->getLine();
7780
}
7881

79-
$exception = FlattenException::createFromThrowable($exception, null, $headers);
82+
$statusCode = 500;
83+
foreach ($this->exceptionsMapping as $class => $config) {
84+
if ($exception instanceof $class && $config['status_code']) {
85+
$statusCode = $config['status_code'];
86+
break;
87+
}
88+
}
89+
$exception = FlattenException::createFromThrowable($exception, $statusCode, $headers);
8090

8191
return $exception->setAsString($this->renderException($exception));
8292
}
@@ -262,8 +272,6 @@ private function formatFile(string $file, int $line, string $text = null): strin
262272
* @param string $file A file path
263273
* @param int $line The selected line number
264274
* @param int $srcContext The number of displayed lines around or -1 for the whole file
265-
*
266-
* @return string
267275
*/
268276
private function fileExcerpt(string $file, int $line, int $srcContext = 3): string
269277
{

‎src/Symfony/Component/ErrorHandler/ErrorRenderer/SerializerErrorRenderer.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/ErrorHandler/ErrorRenderer/SerializerErrorRenderer.php
+16-5Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@ class SerializerErrorRenderer implements ErrorRendererInterface
2828
private $format;
2929
private $fallbackErrorRenderer;
3030
private $debug;
31+
private $exceptionsMapping;
3132

3233
/**
33-
* @param string|callable(FlattenException) $format The format as a string or a callable that should return it
34-
* formats not supported by Request::getMimeTypes() should be given as mime types
35-
* @param bool|callable $debug The debugging mode as a boolean or a callable that should return it
34+
* @param string|callable(FlattenException) $format The format as a string or a callable that should return it
35+
* formats not supported by Request::getMimeTypes() should be given as mime types
36+
* @param bool|callable $debug The debugging mode as a boolean or a callable that should return it
37+
* @param array $exceptionsMapping An exceptions to log & status code mapping
3638
*/
37-
public function __construct(SerializerInterface $serializer, $format, ErrorRendererInterface $fallbackErrorRenderer = null, $debug = false)
39+
public function __construct(SerializerInterface $serializer, $format, ErrorRendererInterface $fallbackErrorRenderer = null, $debug = false, array $exceptionsMapping = [])
3840
{
3941
if (!\is_string($format) && !\is_callable($format)) {
4042
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
4850
$this->format = $format;
4951
$this->fallbackErrorRenderer = $fallbackErrorRenderer ?? new HtmlErrorRenderer();
5052
$this->debug = $debug;
53+
$this->exceptionsMapping = $exceptionsMapping;
5154
}
5255

5356
/**
@@ -62,7 +65,15 @@ public function render(\Throwable $exception): FlattenException
6265
$headers['X-Debug-Exception-File'] = rawurlencode($exception->getFile()).':'.$exception->getLine();
6366
}
6467

65-
$flattenException = FlattenException::createFromThrowable($exception, null, $headers);
68+
$statusCode = 500;
69+
foreach ($this->exceptionsMapping as $class => $config) {
70+
if ($exception instanceof $class && $config['status_code']) {
71+
$statusCode = $config['status_code'];
72+
break;
73+
}
74+
}
75+
76+
$flattenException = FlattenException::createFromThrowable($exception, $statusCode, $headers);
6677

6778
try {
6879
$format = \is_string($this->format) ? $this->format : ($this->format)($flattenException);

‎src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php
+38Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,22 @@ public function getRenderData(): iterable
4040
<html>
4141
%A<title>An Error Occurred: Internal Server Error</title>
4242
%A<h2>The server returned a "500 Internal Server Error".</h2>%A
43+
HTML;
44+
45+
$expectedDebugWithStatusCode = <<<HTML
46+
<!-- Foo (418 I'm a teapot) -->
47+
<!DOCTYPE html>
48+
<html lang="en">
49+
%A<title>Foo (418 I'm a teapot)</title>
50+
%A<div class="trace trace-as-html" id="trace-box-1">%A
51+
<!-- Foo (418 I'm a teapot) -->
52+
HTML;
53+
54+
$expectedNonDebugWithStatusCode = <<<HTML
55+
<!DOCTYPE html>
56+
<html>
57+
%A<title>An Error Occurred: I'm a teapot</title>
58+
%A<h2>The server returned a "418 I'm a teapot".</h2>%A
4359
HTML;
4460

4561
yield '->render() returns the HTML content WITH stack traces in debug mode' => [
@@ -53,5 +69,27 @@ public function getRenderData(): iterable
5369
new HtmlErrorRenderer(false),
5470
$expectedNonDebug,
5571
];
72+
73+
yield '->render() returns the HTML content WITH stack traces in debug mode and contains the correct status code' => [
74+
new \RuntimeException('Foo'),
75+
new HtmlErrorRenderer(true, null, null, null, '', null, [
76+
\RuntimeException::class => [
77+
'status_code' => 418,
78+
'log_level' => null,
79+
],
80+
]),
81+
$expectedDebugWithStatusCode,
82+
];
83+
84+
yield '->render() returns the HTML content WITHOUT stack traces in non-debug mode and contains the correct status code' => [
85+
new \RuntimeException('Foo'),
86+
new HtmlErrorRenderer(false, null, null, null, '', null, [
87+
\RuntimeException::class => [
88+
'status_code' => 418,
89+
'log_level' => null,
90+
],
91+
]),
92+
$expectedNonDebugWithStatusCode,
93+
];
5694
}
5795
}
+91Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
/*
3+
* This file is part of the Symfony package.
4+
*
5+
* (c) Fabien Potencier <fabien@symfony.com>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
11+
namespace Symfony\Component\Serializer\Tests\ErrorRenderer;
12+
13+
use function json_decode;
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\ErrorHandler\ErrorRenderer\SerializerErrorRenderer;
16+
use Symfony\Component\Serializer\Encoder\JsonEncoder;
17+
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
18+
use Symfony\Component\Serializer\Serializer;
19+
20+
/**
21+
* @author Alexey Deriyenko <alexey.deriyenko@gmail.com>
22+
*/
23+
class SerializerErrorRendererTest extends TestCase
24+
{
25+
/**
26+
* @dataProvider getRenderData
27+
*/
28+
public function testRenderReturnsJson(\Throwable $exception, SerializerErrorRenderer $serializerErrorRenderer)
29+
{
30+
$this->assertJson($serializerErrorRenderer->render($exception)->getAsString());
31+
}
32+
33+
/**
34+
* @dataProvider getRenderData
35+
*/
36+
public function testRenderReturnsJsonWithCorrectStatusCode(\Throwable $exception, SerializerErrorRenderer $serializerErrorRenderer, int $expectedStatusCode)
37+
{
38+
$statusCodeFromJson = json_decode($serializerErrorRenderer->render($exception)->getAsString())->statusCode;
39+
$this->assertEquals($expectedStatusCode, $statusCodeFromJson);
40+
}
41+
42+
/**
43+
* @dataProvider getRenderData
44+
*/
45+
public function testRenderReturnsJsonWithCorrectStatusText(\Throwable $exception, SerializerErrorRenderer $serializerErrorRenderer, int $expectedStatusCode, string $expectedStatusText)
46+
{
47+
$statusTextFromJson = json_decode($serializerErrorRenderer->render($exception)->getAsString())->statusText;
48+
$this->assertEquals($expectedStatusText, $statusTextFromJson);
49+
}
50+
51+
public function getRenderData(): iterable
52+
{
53+
yield '->render() returns the JSON content WITH stack traces in debug mode' => [
54+
new \RuntimeException('Foo'),
55+
new SerializerErrorRenderer(new Serializer([new ObjectNormalizer()], [new JsonEncoder()]), 'json', null, true),
56+
500,
57+
'Internal Server Error',
58+
];
59+
60+
yield '->render() returns the JSON content WITHOUT stack traces in non-debug mode' => [
61+
new \RuntimeException('Foo'),
62+
new SerializerErrorRenderer(new Serializer([new ObjectNormalizer()], [new JsonEncoder()]), 'json', null, false),
63+
500,
64+
'Internal Server Error',
65+
];
66+
67+
yield '->render() returns the JSON content WITH stack traces in debug mode and contains the correct status code' => [
68+
new \RuntimeException('Foo'),
69+
new SerializerErrorRenderer(new Serializer([new ObjectNormalizer()], [new JsonEncoder()]), 'json', null, true, [
70+
\RuntimeException::class => [
71+
'status_code' => 418,
72+
'log_level' => null,
73+
],
74+
]),
75+
418,
76+
'I\'m a teapot',
77+
];
78+
79+
yield '->render() returns the JSON content WITHOUT stack traces in non-debug mode and contains the correct status code' => [
80+
new \RuntimeException('Foo'),
81+
new SerializerErrorRenderer(new Serializer([new ObjectNormalizer()], [new JsonEncoder()]), 'json', null, true, [
82+
\RuntimeException::class => [
83+
'status_code' => 418,
84+
'log_level' => null,
85+
],
86+
]),
87+
418,
88+
'I\'m a teapot',
89+
];
90+
}
91+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.