diff --git a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php index 770b96f79e8e347ad9c55461ab8253fd9ff43bc3..2ae21143b2afb438074b245e5162eeebf1cd25f5 100644 --- a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php @@ -147,7 +147,12 @@ protected function makeSubrequest(GetResponseForExceptionEvent $event, $url, $st } $response = $this->httpKernel->handle($sub_request, HttpKernelInterface::SUB_REQUEST); - $response->setStatusCode($status_code); + // Only 2xx responses should have their status code overridden; any + // other status code should be passed on: redirects (3xx), error (5xx)… + // @see https://www.drupal.org/node/2603788#comment-10504916 + if ($response->isSuccessful()) { + $response->setStatusCode($status_code); + } // Persist any special HTTP headers that were set on the exception. if ($exception instanceof HttpExceptionInterface) { diff --git a/core/lib/Drupal/Core/EventSubscriber/HtmlResponsePlaceholderStrategySubscriber.php b/core/lib/Drupal/Core/EventSubscriber/HtmlResponsePlaceholderStrategySubscriber.php index 943b08bd1ee780e4cc646a95ca074e9944dddcef..c67f531cce79a400c58c4331b29ed170bc868432 100644 --- a/core/lib/Drupal/Core/EventSubscriber/HtmlResponsePlaceholderStrategySubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/HtmlResponsePlaceholderStrategySubscriber.php @@ -48,10 +48,6 @@ public function __construct(PlaceholderStrategyInterface $placeholder_strategy) * The event to process. */ public function onRespond(FilterResponseEvent $event) { - if (!$event->isMasterRequest()) { - return; - } - $response = $event->getResponse(); if (!$response instanceof HtmlResponse) { return; diff --git a/core/lib/Drupal/Core/EventSubscriber/HtmlResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/HtmlResponseSubscriber.php index 6fada86d857f7f0c6dc0360e5390a9493c817072..be64602ad8bbd99cc16ade2ce5d4069d3023cdc5 100644 --- a/core/lib/Drupal/Core/EventSubscriber/HtmlResponseSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/HtmlResponseSubscriber.php @@ -42,10 +42,6 @@ public function __construct(AttachmentsResponseProcessorInterface $html_response * The event to process. */ public function onRespond(FilterResponseEvent $event) { - if (!$event->isMasterRequest()) { - return; - } - $response = $event->getResponse(); if (!$response instanceof HtmlResponse) { return; diff --git a/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php b/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php index 5e2835e6abefea5d7cdfa143827375c5edbb58e7..7c817c2cee180d25c782e58674749ff29b82404b 100644 --- a/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php +++ b/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php @@ -6,6 +6,7 @@ */ namespace Drupal\test_page_test\Controller; +use Symfony\Component\HttpKernel\Exception\HttpException; /** * Defines a test controller for page titles. @@ -75,4 +76,14 @@ public function renderPage() { ); } + /** + * Throws a HTTP exception. + * + * @param int $code + * The status code. + */ + public function httpResponseException($code) { + throw new HttpException($code); + } + } diff --git a/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml b/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml index 240842349af3f3c7673f83892af455e0c2b17fbd..a00d0844cef19516de8bf06201fad869b7658f27 100644 --- a/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml +++ b/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml @@ -42,3 +42,11 @@ test_page_test.admin_render_title: _controller: '\Drupal\test_page_test\Controller\Test::renderTitle' requirements: _access: 'TRUE' + +test_page_test.http_response_exception: + path: '/test-http-response-exception/{code}' + defaults: + _controller: '\Drupal\test_page_test\Controller\Test::httpResponseException' + code: 200 + requirements: + _access: 'TRUE' diff --git a/core/tests/Drupal/KernelTests/RequestProcessing/RedirectOnExceptionTest.php b/core/tests/Drupal/KernelTests/RequestProcessing/RedirectOnExceptionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4c7a6860ff172febc8fdfc236cca08309af50304 --- /dev/null +++ b/core/tests/Drupal/KernelTests/RequestProcessing/RedirectOnExceptionTest.php @@ -0,0 +1,50 @@ +<?php + +/** + * @file + * Contains \Drupal\KernelTests\RequestProcessing\RedirectOnExceptionTest. + */ + +namespace Drupal\KernelTests\RequestProcessing; + +use Drupal\KernelTests\KernelTestBase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +/** + * Tests redirects on exception pages. + * + * @group request_processing + */ +class RedirectOnExceptionTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['system', 'test_page_test']; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->installSchema('system', ['router', 'url_alias']); + \Drupal::service('router.builder')->rebuild(); + } + + public function testRedirectOn404() { + \Drupal::configFactory()->getEditable('system.site') + ->set('page.404', '/test-http-response-exception/' . Response::HTTP_PERMANENTLY_REDIRECT) + ->save(); + + /** @var \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel */ + $http_kernel = \Drupal::service('http_kernel'); + + // Foo doesn't exist, so this triggers the 404 page. + $request = Request::create('/foo'); + $response = $http_kernel->handle($request); + $this->assertEquals(Response::HTTP_PERMANENTLY_REDIRECT, $response->getStatusCode()); + } + +}