diff --git a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php index 7601be9ca7..54be66a8fc 100644 --- a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php +++ b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php @@ -45,7 +45,7 @@ class ExceptionController extends ContainerAware $templating = $this->container->get('templating'); $code = $exception->getStatusCode(); - $response = $templating->renderResponse( + return $templating->renderResponse( $this->findTemplate($templating, $format, $code, $this->container->get('kernel')->isDebug()), array( 'status_code' => $code, @@ -55,11 +55,6 @@ class ExceptionController extends ContainerAware 'currentContent' => $currentContent, ) ); - - $response->setStatusCode($code); - $response->headers->replace($exception->getHeaders()); - - return $response; } /** diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php index b35b0fc464..394008332e 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php @@ -35,10 +35,6 @@ class ExceptionControllerTest extends TestCase ->expects($this->once()) ->method('getStatusCode') ->will($this->returnValue(404)); - $this->flatten - ->expects($this->once()) - ->method('getHeaders') - ->will($this->returnValue(array())); $this->controller = new ExceptionController(); $this->kernel = $this->getMock('Symfony\\Component\\HttpKernel\\KernelInterface'); $this->templating = $this->getMockBuilder('Symfony\\Bundle\\TwigBundle\\TwigEngine') diff --git a/src/Symfony/Component/HttpKernel/HttpKernel.php b/src/Symfony/Component/HttpKernel/HttpKernel.php index de51ac51a6..12ebed3503 100644 --- a/src/Symfony/Component/HttpKernel/HttpKernel.php +++ b/src/Symfony/Component/HttpKernel/HttpKernel.php @@ -13,6 +13,7 @@ namespace Symfony\Component\HttpKernel; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; use Symfony\Component\HttpKernel\Event\FilterControllerEvent; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\Event\GetResponseEvent; @@ -191,10 +192,23 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface throw $e; } + $response = $event->getResponse(); + + // ensure that we actually have an error response + if (!$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) { + if ($e instanceof HttpExceptionInterface) { + // keep the HTTP status code and headers + $response->setStatusCode($e->getStatusCode()); + $response->headers->add($e->getHeaders()); + } else { + $response->setStatusCode(500); + } + } + try { - return $this->filterResponse($event->getResponse(), $request, $type); + return $this->filterResponse($response, $request, $type); } catch (\Exception $e) { - return $event->getResponse(); + return $response; } } diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php index 88ff28b051..e1e17012c8 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php @@ -14,8 +14,11 @@ namespace Symfony\Component\HttpKernel\Tests; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\EventDispatcher\EventDispatcher; class HttpKernelTest extends \PHPUnit_Framework_TestCase @@ -59,8 +62,38 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase }); $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new \RuntimeException('foo'); })); + $response = $kernel->handle(new Request()); - $this->assertEquals('foo', $kernel->handle(new Request())->getContent()); + $this->assertEquals('500', $response->getStatusCode()); + $this->assertEquals('foo', $response->getContent()); + } + + public function testHandleExceptionWithARedirectionResponse() + { + $dispatcher = new EventDispatcher(); + $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) { + $event->setResponse(new RedirectResponse('/login', 301)); + }); + + $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new AccessDeniedHttpException(); })); + $response = $kernel->handle(new Request()); + + $this->assertEquals('301', $response->getStatusCode()); + $this->assertEquals('/login', $response->headers->get('Location')); + } + + public function testHandleHttpException() + { + $dispatcher = new EventDispatcher(); + $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) { + $event->setResponse(new Response($event->getException()->getMessage())); + }); + + $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new MethodNotAllowedHttpException(array('POST')); })); + $response = $kernel->handle(new Request()); + + $this->assertEquals('405', $response->getStatusCode()); + $this->assertEquals('POST', $response->headers->get('Allow')); } public function testHandleWhenAListenerReturnsAResponse() diff --git a/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php b/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php index 7094c5444e..f134f9c819 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php @@ -129,7 +129,6 @@ class ExceptionListener $subRequest->attributes->set(SecurityContextInterface::ACCESS_DENIED_ERROR, $exception); $response = $event->getKernel()->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true); - $response->setStatusCode(403); } else { return; }