diff --git a/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php index 9aba7a9..f88272c 100644 --- a/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php @@ -12,6 +12,7 @@ use Drupal\Core\Routing\RequestContext; use Drupal\Core\Routing\UrlGeneratorInterface; use InvalidArgumentException; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\KernelEvents; @@ -100,17 +101,35 @@ public function checkRedirectUrl(FilterResponseEvent $event) { // on RedirectResponse. $url = $response->getTargetUrl(); if (UrlHelper::isExternal($url) && !UrlHelper::externalIsLocal($url, $this->requestContext->getCompleteBaseUrl()) && !$response instanceof RedirectResponseToExternalUrl) { - throw new BadRequestHttpException('Redirects to external URLs are not allowed by default, use \Drupal\Core\Routing\RedirectResponseToExternalUrl for it'); + $this->setBadRequestException($event, 'Redirects to external URLs are not allowed by default, use \Drupal\Core\Routing\RedirectResponseToExternalUrl for it'); } } // Potentially thrown by UrlHelper::externalIsLocal(). catch (\InvalidArgumentException $e) { - throw new BadRequestHttpException($e->getMessage(), $e); + $this->setBadRequestException($event, $e->getMessage()); } } } /** + * Sets the bad request response. + * + * We are not throwing a BadRequestHttpException because filterResponse might + * be executed in the context of an exception handling already. + * + * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event + * The event to update its response + * @param string $message + * The message for response. + */ + protected function setBadRequestException(FilterResponseEvent $event, $message) { + trigger_error($message, E_USER_ERROR); + + $response = new Response($message, 400); + $event->setResponse($response); + } + + /** * Sanitize the destination parameter to prevent open redirect attacks. * * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event diff --git a/core/tests/Drupal/Tests/Core/EventSubscriber/RedirectResponseSubscriberTest.php b/core/tests/Drupal/Tests/Core/EventSubscriber/RedirectResponseSubscriberTest.php index e1ec38f..57c95cb 100644 --- a/core/tests/Drupal/Tests/Core/EventSubscriber/RedirectResponseSubscriberTest.php +++ b/core/tests/Drupal/Tests/Core/EventSubscriber/RedirectResponseSubscriberTest.php @@ -102,7 +102,7 @@ public static function providerTestDestinationRedirect() { /** * @dataProvider providerTestDestinationRedirectToExternalUrl * - * @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException + * @expectedException \PHPUnit_Framework_Error */ public function testDestinationRedirectToExternalUrl($request, $expected) { $dispatcher = new EventDispatcher(); @@ -139,13 +139,7 @@ public function testDestinationRedirectToExternalUrl($request, $expected) { $event = new FilterResponseEvent($kernel, $request, HttpKernelInterface::SUB_REQUEST, $response); $dispatcher->dispatch(KernelEvents::RESPONSE, $event); - $target_url = $event->getResponse()->getTargetUrl(); - if ($expected) { - $this->assertEquals($expected, $target_url); - } - else { - $this->assertEquals('http://example.com/drupal', $target_url); - } + $this->assertEquals(400, $event->getResponse()->getStatusCode()); } /** @@ -193,7 +187,7 @@ public function providerTestDestinationRedirectToExternalUrl() { } /** - * @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException + * @expectedException \PHPUnit_Framework_Error * * @dataProvider providerTestDestinationRedirectWithInvalidUrl */ @@ -211,6 +205,8 @@ public function testDestinationRedirectWithInvalidUrl(Request $request) { $dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'checkRedirectUrl')); $event = new FilterResponseEvent($kernel, $request, HttpKernelInterface::SUB_REQUEST, $response); $dispatcher->dispatch(KernelEvents::RESPONSE, $event); + + $this->assertEquals(400, $event->getResponse()->getStatusCode()); } /**