Skip to content

Commit ffd81ad

Browse files
committed
feature symfony#12096 Add an action to show *error* pages in kernel.debug mode (mpdude)
This PR was squashed before being merged into the 2.6-dev branch (closes symfony#12096). Discussion ---------- Add an action to show *error* pages in kernel.debug mode | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | symfony#7446, symfony#1486, symfony#11327 | License | MIT | Doc PR | symfony/symfony-docs#4293 See symfony#7446 for the initial reasoning. In short, add to your `routing_development.yml` file the following ```yaml _errors: resource: "@TwigBundle/Resources/config/routing/errors.xml" prefix: /_error ``` Then you can use `http://localhost/app_dev.php/_error/xxx` to preview the HTML *error* page that the default `ExceptionController` (from `TwigBundle`) would pick for the XXX status code. You can also use `http://localhost/app_dev.php/_error/xxx.{some_format}` to show error pages for other formats than HTML, most notably `txt`. Note that the status code will be 500 for all exceptions [that do not implement `HttpExceptionInterface`](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Debug/Exception/FlattenException.php#L47). ##### Want to test with a custom exception? ~~Folks might want to display (part of) the exception even on error pages and thus need to work with generic (own) exceptions.~~ ~~They could write an arbitrary controller and throw their exception there. By default, the `ExceptionController` would be used to handle this, only that it would not show *error* pages in `kernel.debug` mode.~~ ~~Thus, a simple public setter to change the `debug` flag after construction could help. Do we want to add that as well?~~ If you want to test error pages with your own exceptions, * create a subclass of `ExceptionController` * set the protected `debug` flag to false * register it as twig.exception_controller in the config * throw your custom exception from any controller. That should give you the error page also in `kernel.debug` mode. ##### To-Do - [x] Update docs - [x] Add route in symfony/symfony-default Commits ------- 66ed177 Add an action to show *error* pages in kernel.debug mode
2 parents 08ff3fd + 66ed177 commit ffd81ad

File tree

3 files changed

+95
-11
lines changed

3 files changed

+95
-11
lines changed

src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
* ExceptionController.
2222
*
2323
* @author Fabien Potencier <fabien@symfony.com>
24+
* @author Matthias Pigulla <mp@webfactory.de>
2425
*/
2526
class ExceptionController
2627
{
@@ -48,18 +49,24 @@ public function showAction(Request $request, FlattenException $exception, DebugL
4849
{
4950
$currentContent = $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level', -1));
5051

51-
$code = $exception->getStatusCode();
52+
return $this->createResponse($request, $exception, $this->debug, $logger, $currentContent);
53+
}
5254

53-
return new Response($this->twig->render(
54-
$this->findTemplate($request, $request->getRequestFormat(), $code, $this->debug),
55-
array(
56-
'status_code' => $code,
57-
'status_text' => isset(Response::$statusTexts[$code]) ? Response::$statusTexts[$code] : '',
58-
'exception' => $exception,
59-
'logger' => $logger,
60-
'currentContent' => $currentContent,
61-
)
62-
));
55+
/**
56+
* Displays the error page for arbitrary status codes and formats.
57+
*
58+
* @param Request $request The request
59+
* @param int $code The HTTP status code to show the error page for.
60+
*
61+
* @return Response
62+
*
63+
* @throws \InvalidArgumentException When the error template does not exist
64+
*/
65+
public function testErrorPageAction(Request $request, $code)
66+
{
67+
$exception = FlattenException::create(new \Exception("Something has intentionally gone wrong."), $code);
68+
69+
return $this->createResponse($request, $exception, false);
6370
}
6471

6572
/**
@@ -130,4 +137,29 @@ protected function templateExists($template)
130137

131138
return false;
132139
}
140+
141+
/**
142+
* @param Request $request
143+
* @param FlattenException $exception
144+
* @param bool $debug
145+
* @param DebugLoggerInterface $logger
146+
* @param string $currentContent
147+
*
148+
* @return Response
149+
*/
150+
protected function createResponse(Request $request, FlattenException $exception, $debug, DebugLoggerInterface $logger = null, $currentContent = '')
151+
{
152+
$code = $exception->getStatusCode();
153+
154+
return new Response($this->twig->render(
155+
$this->findTemplate($request, $request->getRequestFormat(), $code, $debug),
156+
array(
157+
'status_code' => $code,
158+
'status_text' => isset(Response::$statusTexts[$code]) ? Response::$statusTexts[$code] : '',
159+
'exception' => $exception,
160+
'logger' => $logger,
161+
'currentContent' => $currentContent,
162+
)
163+
));
164+
}
133165
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
3+
<routes xmlns="http://symfony.com/schema/routing"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
6+
7+
<route id="_twig_error_test" path="/{code}.{_format}">
8+
<default key="_controller">twig.controller.exception:testErrorPageAction</default>
9+
<default key="_format">html</default>
10+
<requirement key="code">\d+</requirement>
11+
</route>
12+
</routes>

src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,44 @@ public function testOnlyClearOwnOutputBuffers()
4141
$controller = new ExceptionController($twig, false);
4242
$controller->showAction($request, $flatten);
4343
}
44+
45+
public function testErrorPagesInDebugMode()
46+
{
47+
$twig = new \Twig_Environment(
48+
new \Twig_Loader_Array(array(
49+
'TwigBundle:Exception:error404.html.twig' => '
50+
{%- if exception is defined and status_text is defined and status_code is defined -%}
51+
OK
52+
{%- else -%}
53+
"exception" variable is missing
54+
{%- endif -%}
55+
',
56+
))
57+
);
58+
59+
$request = Request::create('whatever');
60+
61+
$controller = new ExceptionController($twig, /* "debug" set to --> */ true);
62+
$response = $controller->testErrorPageAction($request, 404);
63+
64+
$this->assertEquals(200, $response->getStatusCode()); // successful request
65+
$this->assertEquals('OK', $response->getContent()); // content of the error404.html template
66+
}
67+
68+
public function testFallbackToHtmlIfNoTemplateForRequestedFormat()
69+
{
70+
$twig = new \Twig_Environment(
71+
new \Twig_Loader_Array(array(
72+
'TwigBundle:Exception:error.html.twig' => 'html',
73+
))
74+
);
75+
76+
$request = Request::create('whatever');
77+
$request->setRequestFormat('txt');
78+
79+
$controller = new ExceptionController($twig, false);
80+
$response = $controller->testErrorPageAction($request, 42);
81+
82+
$this->assertEquals('html', $request->getRequestFormat());
83+
}
4484
}

0 commit comments

Comments
 (0)