diff --git a/src/Routing/Router.php b/src/Routing/Router.php index d12cd003fac..e6ad88fe00f 100644 --- a/src/Routing/Router.php +++ b/src/Routing/Router.php @@ -618,19 +618,16 @@ public static function url($url = null, $full = false) } if (is_array($url)) { if (isset($url['_ssl'])) { - if (!isset($url['_full'])) { - $url['_scheme'] = ($url['_ssl'] === true) ? 'https' : 'http'; - } - unset($url['_ssl']); + $url['_scheme'] = ($url['_ssl'] === true) ? 'https' : 'http'; } + if (isset($url['_full']) && $url['_full'] === true) { $full = true; - unset($url['_full']); } if (isset($url['#'])) { $frag = '#' . $url['#']; - unset($url['#']); } + unset($url['_ssl'], $url['_full'], $url['#']); $url = static::_applyUrlFilters($url); @@ -655,6 +652,12 @@ public static function url($url = null, $full = false) ]; } + // If a full URL is requested with a scheme the host should default + // to App.fullBaseUrl to avoid corrupt URLs + if ($full && isset($url['_scheme']) && !isset($url['_host'])) { + $url['_host'] = parse_url(static::fullBaseUrl(), PHP_URL_HOST); + } + $output = static::$_collection->match($url, static::$_requestContext + ['params' => $params]); } else { $plainString = ( @@ -681,11 +684,6 @@ public static function url($url = null, $full = false) } } - $protocolError = preg_match('#^[a-z][a-z0-9+\-.]*\:///#i', $output); - if ($protocolError === 1) { - $output = str_replace(':///', '://', $output); - } - return $output . $frag; } diff --git a/tests/TestCase/Routing/RouterTest.php b/tests/TestCase/Routing/RouterTest.php index dbb8f9afc24..352df7243c0 100644 --- a/tests/TestCase/Routing/RouterTest.php +++ b/tests/TestCase/Routing/RouterTest.php @@ -2059,6 +2059,46 @@ public function testGenerationWithSslOption() $this->assertEquals('http://localhost/images/index', $result); } + /** + * Test that the _ssl + _full options work together. + * + * @return void + */ + public function testGenerationWithSslAndFullOption() + { + Configure::write('App.fullBaseUrl', 'http://app.localhost'); + Router::connect('/:controller/:action/*'); + + $request = new ServerRequest([ + 'environment' => ['HTTP_HOST' => 'localhost'] + ]); + Router::pushRequest($request); + + $result = Router::url([ + 'controller' => 'images', + 'action' => 'index', + '_ssl' => true, + '_full' => true + ]); + $this->assertEquals('https://app.localhost/images/index', $result); + + $result = Router::url([ + 'controller' => 'images', + 'action' => 'index', + '_ssl' => false, + '_full' => true, + ]); + $this->assertEquals('http://app.localhost/images/index', $result); + + $result = Router::url([ + 'controller' => 'images', + 'action' => 'index', + '_full' => false, + '_ssl' => false + ]); + $this->assertEquals('http://localhost/images/index', $result); + } + /** * Test ssl option when the current request is ssl. *