8000 [HttpKernel][FrameworkBundle] Turn HTTP exceptions to HTTP status cod… · symfony/symfony@5139ef9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5139ef9

Browse files
[HttpKernel][FrameworkBundle] Turn HTTP exceptions to HTTP status codes by default
1 parent 50c4384 commit 5139ef9

File tree

5 files changed

+68
-9
lines changed

5 files changed

+68
-9
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,17 @@
6767
<argument type="service" id="router" on-invalid="ignore" />
6868
</service>
6969

70+
<service id="http_exception_listener" class="Symfony\Component\HttpKernel\EventListener\ExceptionListener">
71+
<tag name="kernel.event_listener" event="kernel.exception" method="onKernelException" priority="-2048" />
72+
<tag name="monolog.logger" channel="request" />
73+
<tag name="kernel.reset" method="reset" />
74+
<argument>null</argument>
75+
<argument type="service" id="logger" on-invalid="null" />
76+
<argument>%kernel.debug%</argument>
77+
<argument>%kernel.charset%</argument>
78+
<argument>%debug.file_link_format%</argument>
79+
</service>
80+
7081
<service id="validate_request_listener" class="Symfony\Component\HttpKernel\EventListener\ValidateRequestListener">
7182
<tag name="kernel.event_subscriber" />
7283
</service>

src/Symfony/Bundle/SecurityBundle/Tests/Functional/MissingUserProviderTest.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,6 @@
1515

1616
class MissingUserProviderTest extends WebTestCase
1717
{
18-
/**
19-
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
20-
* @expectedExceptionMessage "default" firewall requires a user provider but none was defined.
21-
*/
2218
public function testUserProviderIsNeeded()
2319
{
2420
$client = $this->createClient(array('test_case' => 'MissingUserProvider', 'root_config' => 'config.yml'));
@@ -27,5 +23,11 @@ public function testUserProviderIsNeeded()
2723
'PHP_AUTH_USER' => 'username',
2824
'PHP_AUTH_PW' => 'pa$$word',
2925
));
26+
27+
$response = $client->getResponse();
28+
29+
$this->assertSame(500, $response->getStatusCode());
30+
$this->assertContains(InvalidConfigurationException::class, $response->getContent());
31+
$this->assertContains('"default" firewall requires a user provider but none was defined', htmlspecialchars_decode($response->getContent()));
3032
}
3133
}

src/Symfony/Bundle/SecurityBundle/composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"symfony/dom-crawler": "~3.4|~4.0",
3131
"symfony/event-dispatcher": "~3.4|~4.0",
3232
"symfony/form": "~3.4|~4.0",
33-
"symfony/framework-bundle": "~4.1",
33+
"symfony/framework-bundle": "~4.2",
3434
"symfony/http-foundation": "~3.4|~4.0",
3535
"symfony/translation": "~3.4|~4.0",
3636
"symfony/twig-bundle": "~3.4|~4.0",
@@ -46,7 +46,7 @@
4646
"conflict": {
4747
"symfony/var-dumper": "<3.4",
4848
"symfony/event-dispatcher": "<3.4",
49-
"symfony/framework-bundle": "<4.1.1",
49+
"symfony/framework-bundle": "<4.2",
5050
"symfony/console": "<3.4"
5151
},
5252
"autoload": {

src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
namespace Symfony\Component\HttpKernel\EventListener;
1313

1414
use Psr\Log\LoggerInterface;
15+
use Symfony\Component\Debug\ExceptionHandler;
1516
use Symfony\Component\Debug\Exception\FlattenException;
1617
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
1718
use Symfony\Component\HttpFoundation\Request;
19+
use Symfony\Component\HttpFoundation\Response;
1820
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
1921
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
2022
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
@@ -33,16 +35,32 @@ class ExceptionListener implements EventSubscriberInterface
3335
protected $controller;
3436
protected $logger;
3537
protected $debug;
38+
private $charset;
39+
private $fileLinkFormat;
40+
private $isTerminating = false;
3641

37-
public function __construct($controller, LoggerInterface $logger = null, $debug = false)
42+
public function __construct($controller, LoggerInterface $logger = null, $debug = false, $charset = null, $fileLinkFormat = null)
3843
{
3944
$this->controller = $controller;
4045
$this->logger = $logger;
4146
$this->debug = $debug;
47+
$this->charset = $charset;
48+
$this->fileLinkFormat = $fileLinkFormat;
4249
}
4350

4451
public function logKernelException(GetResponseForExceptionEvent $event)
4552
{
53+
if (null === $this->controller) {
54+
if (!$event->isMasterRequest()) {
55+
return;
56+
}
57+
if (!$this->isTerminating) {
58+
$this->isTerminating = true;
59+
60+
return;
61+
}
62+
$this->isTerminating = false;
63+
}
4664
$exception = $event->getException();
4765
$request F438 = $event->getRequest();
4866

@@ -86,6 +104,11 @@ public function onKernelException(GetResponseForExceptionEvent $event)
86104
}
87105
}
88106

107+
public function reset()
108+
{
109+
$this->isTerminating = false;
110+
}
111+
89112
public static function getSubscribedEvents()
90113
{
91114
return array(
@@ -124,8 +147,12 @@ protected function logException(\Exception $exception, $message)
124147
protected function duplicateRequest(\Exception $exception, Request $request)
125148
{
126149
$attributes = array(
127-
'_controller' => $this->controller,
128-
'exception' => FlattenException::create($exception),
150+
'exception' => $exception = FlattenException::create($exception),
151+
'_controller' => $this->controller ?: function () use ($exception) {
152+
$handler = new ExceptionHandler($this->debug, $this->charset, $this->fileLinkFormat);
153+
154+
return new Response($handler->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders());
155+
},
129156
'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null,
130157
);
131158
$request = $request->duplicate(null, null, $attributes);

src/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,25 @@ public function testCSPHeaderIsRemoved()
155155
$this->assertFalse($response->headers->has('content-security-policy'), 'CSP header has been removed');
156156
$this->assertFalse($dispatcher->hasListeners(KernelEvents::RESPONSE), 'CSP removal listener has been removed');
157157
}
158+
159+
public function testNullController()
160+
{
161+
$listener = new ExceptionListener(null);
162+
$kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
163+
$kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) {
164+
$controller = $request->attributes->get('_controller');
165+
166+
return $controller();
167+
}));
168+
$request = Request::create('/');
169+
$event = new GetResponseForExceptionEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, new \Exception('foo'));
170+
171+
$listener->onKernelException($event);
172+
$this->assertNull($event->getResponse());
173+
174+
$listener->onKernelException($event);
175+
$this->assertContains('Whoops, looks like something went wrong.', $event->getResponse()->getContent());
176+
}
158177
}
159178

160179
class TestLogger extends Logger implements DebugLoggerInterface

0 commit comments

Comments
 (0)
0