bug #23052 [TwigBundle] Add Content-Type header for exception response (rchoquet)

This PR was merged into the 2.7 branch.

Discussion
----------

[TwigBundle] Add Content-Type header for exception response

| Q             | A
| ------------- | ---
| Branch?       | 2.7
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets |
| License       | MIT
| Doc PR        |

This PR comes after I was looking to customize the way exceptions are served for a JSON API (grabbed the info at http://symfony.com/doc/current/controller/error_pages.html#overriding-the-default-exceptioncontroller).

I noticed that even when changing the request format to 'json' so that the right json.twig template is served:
```php
// in my override of the ExceptionController
public function showAction(Request $request, FlattenException $exception, DebugLoggerInterface $logger = null)
{
    $request->setRequestFormat('json');
    return parent::showAction($request, $exception, $logger);
}
```
the response Content-Type header was still 'text/html'.

By now, the response Content-Type should be corresponding to the given request format.

I also feel there's some room for improvement with the general "displaying error for a JSON API" chapter as it feels strange that there's no configuration option to just say "serve me anything as json", but that's another issue.

Commits
-------

9e2b408f25 add content-type header on exception response
This commit is contained in:
Fabien Potencier 2017-06-16 08:39:36 -07:00
commit c8884e7d9a
2 changed files with 35 additions and 18 deletions

View File

@ -74,7 +74,7 @@ class ExceptionController
'logger' => $logger,
'currentContent' => $currentContent,
)
));
), 200, array('Content-Type' => $request->getMimeType($request->getRequestFormat()) ?: 'text/html'));
}
/**

View File

@ -22,14 +22,9 @@ class ExceptionControllerTest extends TestCase
{
public function testShowActionCanBeForcedToShowErrorPage()
{
$twig = new Environment(
new ArrayLoader(array(
'TwigBundle:Exception:error404.html.twig' => 'ok',
))
);
$twig = $this->createTwigEnv(array('TwigBundle:Exception:error404.html.twig' => '<html>not found</html>'));
$request = Request::create('whatever', 'GET');
$request->headers->set('X-Php-Ob-Level', 1);
$request = $this->createRequest('html');
$request->attributes->set('showException', false);
$exception = FlattenException::create(new \Exception(), 404);
$controller = new ExceptionController($twig, /* "showException" defaults to --> */ true);
@ -37,25 +32,47 @@ class ExceptionControllerTest extends TestCase
$response = $controller->showAction($request, $exception, null);
$this->assertEquals(200, $response->getStatusCode()); // successful request
$this->assertEquals('ok', $response->getContent()); // content of the error404.html template
$this->assertEquals('<html>not found</html>', $response->getContent());
}
public function testFallbackToHtmlIfNoTemplateForRequestedFormat()
{
$twig = new Environment(
new ArrayLoader(array(
'TwigBundle:Exception:error.html.twig' => 'html',
))
);
$twig = $this->createTwigEnv(array('TwigBundle:Exception:error.html.twig' => '<html></html>'));
$request = Request::create('whatever');
$request->headers->set('X-Php-Ob-Level', 1);
$request->setRequestFormat('txt');
$request = $this->createRequest('txt');
$exception = FlattenException::create(new \Exception());
$controller = new ExceptionController($twig, false);
$controller->showAction($request, $exception);
$this->assertEquals('html', $request->getRequestFormat());
}
public function testResponseHasRequestedMimeType()
{
$twig = $this->createTwigEnv(array('TwigBundle:Exception:error.json.twig' => '{}'));
$request = $this->createRequest('json');
$exception = FlattenException::create(new \Exception());
$controller = new ExceptionController($twig, false);
$response = $controller->showAction($request, $exception);
$this->assertEquals('html', $request->getRequestFormat());
$this->assertEquals('json', $request->getRequestFormat());
$this->assertEquals($request->getMimeType('json'), $response->headers->get('Content-Type'));
}
private function createRequest($requestFormat)
{
$request = Request::create('whatever');
$request->headers->set('X-Php-Ob-Level', 1);
$request->setRequestFormat($requestFormat);
return $request;
}
private function createTwigEnv(array $templates)
{
return new Environment(new ArrayLoader($templates));
}
}