diff --git a/core/modules/system/src/Tests/Session/SessionHttpsTest.php b/core/modules/system/src/Tests/Session/SessionHttpsTest.php index a2621c9..3976860 100644 --- a/core/modules/system/src/Tests/Session/SessionHttpsTest.php +++ b/core/modules/system/src/Tests/Session/SessionHttpsTest.php @@ -246,7 +246,17 @@ protected function testCsrfTokenWithMixedModeSsl() { $form[0]['action'] = $this->httpsUrl('session-test/form'); $edit = array('input' => $this->randomName(32)); $this->curlClose(); + + $maximum_redirects = $this->maximumRedirects; + $this->maximumRedirects = 0; $this->drupalPostForm(NULL, $edit, 'Save', array('Cookie: ' . $this->secureSessionName . '=' . $ssid)); + $this->maximumRedirects = $maximum_redirects; + + // Follow the redirect header. + $path = $this->getPathFromLocationHeader(TRUE); + $this->drupalGet($this->httpUrl($path)); + $this->assertResponse(200); + $this->assertText(String::format('Ok: @input', array('@input' => $edit['input']))); // Retrieve the same form via HTTPS. @@ -265,13 +275,24 @@ protected function testCsrfTokenWithMixedModeSsl() { * Note that the parents $session_id and $loggedInUser is not updated. */ protected function loginHttp(AccountInterface $account) { + $this->drupalGet('user'); + // Alter the form action to submit the login form through http.php, which // creates a mock HTTP request on HTTPS test environments. - $this->drupalGet('user'); $form = $this->xpath('//form[@id="user-login-form"]'); $form[0]['action'] = $this->httpUrl('user'); $edit = array('name' => $account->getUsername(), 'pass' => $account->pass_raw); + + // Post the form, but prevent curl to handle redirects. + $maximum_redirects = $this->maximumRedirects; + $this->maximumRedirects = 0; $this->drupalPostForm(NULL, $edit, t('Log in')); + $this->maximumRedirects = $maximum_redirects; + + // Follow the location header. + $path = $this->getPathFromLocationHeader(FALSE); + $this->drupalGet($this->httpUrl($path)); + $this->assertResponse(200); } /** @@ -280,13 +301,50 @@ protected function loginHttp(AccountInterface $account) { * Note that the parents $session_id and $loggedInUser is not updated. */ protected function loginHttps(AccountInterface $account) { + $this->drupalGet('user'); + // Alter the form action to submit the login form through https.php, which // creates a mock HTTPS request on HTTP test environments. - $this->drupalGet('user'); $form = $this->xpath('//form[@id="user-login-form"]'); $form[0]['action'] = $this->httpsUrl('user'); $edit = array('name' => $account->getUsername(), 'pass' => $account->pass_raw); + + // Post the form, but prevent curl to handle redirects. + $maximum_redirects = $this->maximumRedirects; + $this->maximumRedirects = 0; $this->drupalPostForm(NULL, $edit, t('Log in')); + $this->maximumRedirects = $maximum_redirects; + + // Follow the location header. + $path = $this->getPathFromLocationHeader(TRUE); + $this->drupalGet($this->httpUrl($path)); + $this->assertResponse(200); + } + + /** + * Extract internal path from the location header on the response. + */ + protected function getPathFromLocationHeader($https = FALSE, $response_code = 302) { + // Generate the base_url. + $base_url = $this->container->get('url_generator')->generateFromPath('', array('absolute' => TRUE)); + if ($https) { + $base_url = str_replace('http://', 'https://', $base_url); + } + else { + $base_url = str_replace('https://', 'http://', $base_url); + } + + // The mock front controllers (http.php and https.php) add the script name + // to $_SERVER['REQEUST_URI'] and friends. Therefore it is necessary to + // strip that also. + $base_url . 'index.php/'; + + // Extract relative path from location header. + $this->assertResponse($response_code); + $location = $this->drupalGetHeader('location'); + + $this->assertIdentical(strpos($location, $base_url), 0, 'Location header contains expected base URL'); + return substr($location, strlen($location)); } /** diff --git a/core/modules/system/tests/http.php b/core/modules/system/tests/http.php index 662031f..d5fa142 100644 --- a/core/modules/system/tests/http.php +++ b/core/modules/system/tests/http.php @@ -5,9 +5,6 @@ * Fake an HTTP request, for use during testing. */ -// Set a global variable to indicate a mock HTTP request. -$is_http_mock = !empty($_SERVER['HTTPS']); - // Change to HTTP. $_SERVER['HTTPS'] = NULL; ini_set('session.cookie_secure', FALSE); diff --git a/core/modules/system/tests/https.php b/core/modules/system/tests/https.php index 247e6e5..6222c60 100644 --- a/core/modules/system/tests/https.php +++ b/core/modules/system/tests/https.php @@ -8,9 +8,6 @@ * see http.php. */ -// Set a global variable to indicate a mock HTTPS request. -$is_https_mock = empty($_SERVER['HTTPS']); - // Change to HTTPS. $_SERVER['HTTPS'] = 'on'; foreach ($_SERVER as $key => $value) { diff --git a/core/modules/system/tests/modules/session_test/src/EventSubscriber/SessionTestSubscriber.php b/core/modules/system/tests/modules/session_test/src/EventSubscriber/SessionTestSubscriber.php index 41ccdf0..f4c9a44 100644 --- a/core/modules/system/tests/modules/session_test/src/EventSubscriber/SessionTestSubscriber.php +++ b/core/modules/system/tests/modules/session_test/src/EventSubscriber/SessionTestSubscriber.php @@ -8,7 +8,6 @@ namespace Drupal\session_test\EventSubscriber; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\Event\GetResponseEvent; @@ -18,8 +17,10 @@ */ class SessionTestSubscriber implements EventSubscriberInterface { - /* + /** * Stores whether $_SESSION is empty at the beginning of the request. + * + * @var bool */ protected $emptySession; @@ -40,20 +41,8 @@ public function onKernelRequestSessionTest(GetResponseEvent $event) { * The Event to process. */ public function onKernelResponseSessionTest(FilterResponseEvent $event) { - $response = $event->getResponse(); - if ($response instanceOf RedirectResponse) { - // Force the redirection to go to a non-secure page after being on a - // secure page through https.php. - global $is_https_mock; - // Alter the redirect to use HTTP when using a mock HTTPS request through - // https.php because form submissions would otherwise redirect to a - // non-existent HTTPS site. - if (!empty($is_https_mock)) { - $path = str_replace('https://', 'http://', $response->getTargetUrl()); - $response->setTargetUrl($path); - } - } // Set header for session testing. + $response = $event->getResponse(); $response->headers->set('X-Session-Empty', $this->emptySession); } @@ -64,7 +53,7 @@ public function onKernelResponseSessionTest(FilterResponseEvent $event) { * An array of event listener definitions. */ public static function getSubscribedEvents() { - $events[KernelEvents::RESPONSE][] = array('onKernelResponseSessionTest', 300); + $events[KernelEvents::RESPONSE][] = array('onKernelResponseSessionTest'); $events[KernelEvents::REQUEST][] = array('onKernelRequestSessionTest'); return $events; }