Skip to content

Commit

Permalink
Make routes use host conditions to generate URLs
Browse files Browse the repository at this point in the history
Make routes that use _host conditions, also apply those conditions
during URL generation. For routes with simple host conditions, we can
always generate an absolute URL. For wildcard host conditions, we'll
require either the request context to be correct, or for a route
parameter to be provided.

Refs #10057
  • Loading branch information
markstory committed Jan 18, 2017
1 parent 58590c5 commit eff8d9a
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 3 deletions.
22 changes: 19 additions & 3 deletions src/Routing/Route/Route.php
Expand Up @@ -480,7 +480,7 @@ public function match(array $url, array $context = [])
$this->compile();
}
$defaults = $this->defaults;
$context += ['params' => []];
$context += ['params' => [], '_port' => null, '_scheme' => null, '_host' => null];

if (!empty($this->options['persist']) &&
is_array($this->options['persist'])
Expand All @@ -503,6 +503,21 @@ public function match(array $url, array $context = [])
}
}

// Apply the _host option if possible
if (isset($this->options['_host'])) {
if (!isset($hostOptions['_host']) && strpos($this->options['_host'], '*') === false) {
$hostOptions['_host'] = $this->options['_host'];
}
if (!isset($hostOptions['_host'])) {
$hostOptions['_host'] = $context['_host'];
}

// The host did not match the route preferences
if (!$this->hostMatches($hostOptions['_host'])) {
return false;
}
}

// If no base is set, copy one in.
if (!isset($hostOptions['_base']) && isset($context['_base'])) {
$hostOptions['_base'] = $context['_base'];
Expand Down Expand Up @@ -671,11 +686,12 @@ protected function _writeUrl($params, $pass = [], $query = [])
) {
$host = $params['_host'];

// append the port if it exists.
// append the port & scheme if they exists.
if (isset($params['_port'])) {
$host .= ':' . $params['_port'];
}
$out = "{$params['_scheme']}://{$host}{$out}";
$scheme = isset($params['_scheme']) ? $params['_scheme'] : 'http';
$out = "{$scheme}://{$host}{$out}";
}
if (!empty($params['_ext']) || !empty($query)) {
$out = rtrim($out, '/');
Expand Down
68 changes: 68 additions & 0 deletions tests/TestCase/Routing/Route/RouteTest.php
Expand Up @@ -537,6 +537,8 @@ public function testMatchWithPersistOption()

/**
* Test match() with _host and other keys.
*
* @return void
*/
public function testMatchWithHostKeys()
{
Expand Down Expand Up @@ -585,6 +587,72 @@ public function testMatchWithHostKeys()
$this->assertEquals('https://example.com:8080/dir/posts/index', $result);
}

/**
* Test that the _host option sets the default host.
*
* @return void
*/
public function testMatchWithHostOption()
{
$route = new Route(
'/fallback',
['controller' => 'Articles', 'action' => 'index'],
['_host' => 'www.example.com']
);
$result = $route->match([
'controller' => 'Articles',
'action' => 'index'
]);
$this->assertSame('http://www.example.com/fallback', $result);
}

/**
* Test wildcard host options
*
* @return void
*/
public function testMatchWithHostWildcardOption()
{
$route = new Route(
'/fallback',
['controller' => 'Articles', 'action' => 'index'],
['_host' => '*.example.com']
);
$result = $route->match([
'controller' => 'Articles',
'action' => 'index'
]);
$this->assertFalse($result, 'No request context means no match');

$result = $route->match([
'controller' => 'Articles',
'action' => 'index',
], ['_host' => 'wrong.com']);
$this->assertFalse($result, 'Request context has bad host');

$result = $route->match([
'controller' => 'Articles',
'action' => 'index',
'_host' => 'wrong.com'
]);
$this->assertFalse($result, 'Url param is wrong');

$result = $route->match([
'controller' => 'Articles',
'action' => 'index',
'_host' => 'foo.example.com'
]);
$this->assertSame('http://foo.example.com/fallback', $result);

$result = $route->match([
'controller' => 'Articles',
'action' => 'index',
], [
'_host' => 'foo.example.com'
]);
$this->assertSame('http://foo.example.com/fallback', $result);
}

/**
* Test that non-greedy routes fail with extra passed args
*
Expand Down
28 changes: 28 additions & 0 deletions tests/TestCase/Routing/RouterTest.php
Expand Up @@ -558,6 +558,34 @@ public function testUrlGenerationWithBasePath()
$this->assertEquals('/magazine/articles/view/1', $result);
}

/**
* Test url() with _host option routes with request context
*
* @return void
*/
public function testUrlGenerationHostOptionRequestContext()
{
$server = [
'HTTP_HOST' => 'foo.example.com',
'DOCUMENT_ROOT' => '/Users/markstory/Sites',
'SCRIPT_FILENAME' => '/Users/markstory/Sites/subdir/webroot/index.php',
'PHP_SELF' => '/subdir/webroot/index.php/articles/view/1',
'REQUEST_URI' => '/subdir/articles/view/1',
'QUERY_STRING' => '',
'SERVER_PORT' => 80,
];

Router::connect('/fallback', ['controller' => 'Articles'], ['_host' => '*.example.com']);
$request = ServerRequestFactory::fromGlobals($server);
Router::setRequestContext($request);

$result = Router::url(['controller' => 'Articles', 'action' => 'index']);
$this->assertEquals('http://foo.example.com/subdir/fallback', $result);

$result = Router::url(['controller' => 'Articles', 'action' => 'index'], true);
$this->assertEquals('http://foo.example.com/subdir/fallback', $result);
}

/**
* Test that catch all routes work with a variety of falsey inputs.
*
Expand Down

0 comments on commit eff8d9a

Please sign in to comment.