Skip to content

Commit

Permalink
Throw exceptions when routes result in an error.
Browse files Browse the repository at this point in the history
When parsing routes throw an error when an incoming URL does not match
any connected routes. This error will be used to generate a more helpful
error page.
  • Loading branch information
markstory committed Jul 2, 2014
1 parent ac16ff1 commit a9ba33d
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 47 deletions.
26 changes: 26 additions & 0 deletions src/Routing/Error/MissingRouteException.php
@@ -0,0 +1,26 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://book.cakephp.org/2.0/en/development/testing.html
* @since 3.0.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Routing\Error;

use Cake\Error\Exception;

/**
* Exception raised when a URL cannot be reverse routed
* or when a URL cannot be parsed.
*/
class MissingRouteException extends Exception {

protected $_messageTemplate = 'A route matching "%s" could not be found.';

}
10 changes: 7 additions & 3 deletions src/Routing/Router.php
Expand Up @@ -493,10 +493,14 @@ public static function parse($url) {

foreach (static::$_pathScopes as $path => $collection) {
if (strpos($url, $path) === 0) {
return $collection->parse($url);
break;
}
}
throw new MissingRouteException($url);
$result = $collection->parse($url);
if ($result) {
return $result;
}
throw new MissingRouteException(['url' => $url]);
}

/**
Expand Down Expand Up @@ -848,7 +852,7 @@ protected static function _match($url) {
}
}

throw new MissingRouteException(var_export($url, true));
throw new MissingRouteException(['url' => var_export($url, true)]);
}

/**
Expand Down
2 changes: 2 additions & 0 deletions tests/TestCase/Controller/Component/AuthComponentTest.php
Expand Up @@ -979,6 +979,8 @@ public function testStatelessAuthWorksWithUser() {
* @return void
*/
public function testComponentSettings() {
Router::connect('/:controller');

$request = new Request();
$this->Controller = new AuthTestController($request, $this->getMock('Cake\Network\Response'));

Expand Down
67 changes: 23 additions & 44 deletions tests/TestCase/Routing/RouterTest.php
Expand Up @@ -186,10 +186,6 @@ public function testMapResources() {
$result = Router::parse('/posts/13');
$this->assertEquals($expected, $result);

$_SERVER['REQUEST_METHOD'] = 'GET';
$result = Router::parse('/posts/add');
$this->assertSame([], $result);

Router::reload();
$result = Router::mapResources('Posts', ['id' => '[a-z0-9_]+']);
$this->assertEquals(['posts'], $result);
Expand Down Expand Up @@ -590,7 +586,6 @@ public function testUrlGenerationBasic() {

Router::reload();
Router::connect('/:plugin/:id/*', array('controller' => 'posts', 'action' => 'view'), array('id' => $ID));
Router::parse('/');

$result = Router::url(array(
'plugin' => 'cake_plugin',
Expand All @@ -613,15 +608,13 @@ public function testUrlGenerationBasic() {

Router::reload();
Router::connect('/:controller/:action/:id', [], array('id' => $ID));
Router::parse('/');

$result = Router::url(array('controller' => 'posts', 'action' => 'view', 'id' => '1'));
$expected = '/posts/view/1';
$this->assertEquals($expected, $result);

Router::reload();
Router::connect('/:controller/:id', array('action' => 'view'));
Router::parse('/');

$result = Router::url(array('controller' => 'posts', 'action' => 'view', 'id' => '1'));
$expected = '/posts/1';
Expand All @@ -634,7 +627,6 @@ public function testUrlGenerationBasic() {

Router::reload();
Router::connect('/:controller/:action');
Router::parse('/');
$request = new Request();
$request->addParams(array(
'action' => 'index',
Expand All @@ -652,7 +644,6 @@ public function testUrlGenerationBasic() {

Router::reload();
Router::connect('/contact/:action', array('plugin' => 'contact', 'controller' => 'contact'));
Router::parse('/');

$result = Router::url(array(
'plugin' => 'contact',
Expand Down Expand Up @@ -780,7 +771,6 @@ public function testUrlGenerationWithRegexQualifiedParams() {
array('plugin' => 'shows', 'controller' => 'shows', 'action' => 'calendar'),
array('month' => '0[1-9]|1[012]', 'year' => '[12][0-9]{3}')
);
Router::parse('/');

$result = Router::url(array(
'plugin' => 'shows',
Expand All @@ -799,7 +789,6 @@ public function testUrlGenerationWithRegexQualifiedParams() {
array('month' => '0[1-9]|1[012]', 'year' => '[12][0-9]{3}')
);
Router::connect('/kalender/*', array('plugin' => 'shows', 'controller' => 'shows', 'action' => 'calendar'));
Router::parse('/');

$result = Router::url(array('plugin' => 'shows', 'controller' => 'shows', 'action' => 'calendar', 'min-forestilling'));
$expected = '/kalender/min-forestilling';
Expand Down Expand Up @@ -852,7 +841,6 @@ public function testUrlGenerationWithPrefix() {
Router::reload();
Router::connect('/admin/subscriptions/:action/*', array('controller' => 'subscribe', 'prefix' => 'admin'));
Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
Router::parse('/');

$request = new Request();
$request->addParams(array(
Expand Down Expand Up @@ -888,7 +876,6 @@ public function testUrlGenerationWithPrefix() {
Router::setRequestInfo($request);

Router::connect('/page/*', array('controller' => 'pages', 'action' => 'view', 'prefix' => 'admin'));
Router::parse('/');

$result = Router::url(array('prefix' => 'admin', 'controller' => 'pages', 'action' => 'view', 'my-page'));
$expected = '/page/my-page';
Expand All @@ -908,15 +895,13 @@ public function testUrlGenerationWithPrefix() {
$request->here = '/admin/pages/add';
$request->webroot = '/';
Router::setRequestInfo($request);
Router::parse('/');

$result = Router::url(array('plugin' => null, 'controller' => 'pages', 'action' => 'add', 'id' => false));
$expected = '/admin/pages/add';
$this->assertEquals($expected, $result);

Router::reload();
Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
Router::parse('/');
$request = new Request();
$request->addParams(array(
'plugin' => null,
Expand All @@ -935,7 +920,6 @@ public function testUrlGenerationWithPrefix() {

Router::reload();
Router::connect('/admin/:controller/:action/:id', array('prefix' => 'admin'), array('id' => '[0-9]+'));
Router::parse('/');
$request = new Request();
Router::setRequestInfo(
$request->addParams(array(
Expand All @@ -957,7 +941,6 @@ public function testUrlGenerationWithPrefix() {

Router::reload();
Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
Router::parse('/');

$request = new Request();
Router::setRequestInfo(
Expand All @@ -974,7 +957,6 @@ public function testUrlGenerationWithPrefix() {

Router::reload();
Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
Router::parse('/');

$request = new Request();
Router::setRequestInfo(
Expand All @@ -992,7 +974,6 @@ public function testUrlGenerationWithPrefix() {

Router::reload();
Router::connect('/admin/posts/*', array('controller' => 'posts', 'action' => 'index', 'prefix' => 'admin'));
Router::parse('/');
Router::setRequestInfo(
$request->addParams(array(
'plugin' => null, 'controller' => 'posts', 'action' => 'index', 'prefix' => 'admin',
Expand All @@ -1015,7 +996,6 @@ public function testUrlGenerationWithPrefix() {
public function testUrlGenerationWithExtensions() {
Router::connect('/:controller', array('action' => 'index'));
Router::connect('/:controller/:action');
Router::parse('/');

$result = Router::url(array(
'plugin' => null,
Expand Down Expand Up @@ -1459,7 +1439,6 @@ public function testRouteSymmetry() {
array('controller' => 'pages', 'action' => 'view', 'extra' => null),
array("extra" => '[a-z1-9_]*', "slug" => '[a-z1-9_]+')
);
Router::parse('/');

$result = Router::url(array(
'admin' => null,
Expand All @@ -1484,6 +1463,16 @@ public function testRouteSymmetry() {
$this->assertEquals($expected, $result);
}

/**
* Test exceptions when parsing fails.
*
* @expectedException Cake\Routing\Error\MissingRouteException
*/
public function testParseError() {
Router::connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']);
Router::parse('/nope');
}

/**
* Test parse and reverse symmetry
*
Expand All @@ -1502,7 +1491,6 @@ public function testParseReverseSymmetry($url) {
*/
public function parseReverseSymmetryData() {
return array(
array('/'),
array('/controller/action'),
array('/controller/action/param'),
array('/controller/action?param1=value1&param2=value2'),
Expand Down Expand Up @@ -1559,7 +1547,6 @@ public function testPrefixRoutingAndPlugins() {
'webroot' => '/base/',
))
);
Router::parse('/');

$result = Router::url(array(
'plugin' => 'test_plugin',
Expand Down Expand Up @@ -1738,8 +1725,6 @@ public function testUrlGenerationWithAutoPrefixes() {
Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
Router::connect('/:controller/:action/*');

Router::parse('/');

$request = new Request();
Router::setRequestInfo(
$request->addParams(array(
Expand Down Expand Up @@ -1863,7 +1848,6 @@ public function testPrefixRoutePersistence() {
Router::reload();
Router::connect('/protected/:controller/:action', array('prefix' => 'protected'));
Router::connect('/:controller/:action');
Router::parse('/');

$request = new Request();
Router::setRequestInfo(
Expand Down Expand Up @@ -2058,6 +2042,7 @@ public function testParsingWithTrailingPeriodAndParseExtensions() {
/**
* test that patterns work for :action
*
* @expectedException Cake\Routing\Error\MissingRouteException
* @return void
*/
public function testParsingWithPatternOnAction() {
Expand All @@ -2076,8 +2061,7 @@ public function testParsingWithPatternOnAction() {
);
$this->assertEquals($expected, $result);

$result = Router::parse('/blog/foobar');
$this->assertSame([], $result);
Router::parse('/blog/foobar');
}

/**
Expand All @@ -2086,7 +2070,7 @@ public function testParsingWithPatternOnAction() {
* @expectedException Cake\Routing\Error\MissingRouteException
* @return void
*/
public function testUrlPatterOnAction() {
public function testUrlPatternOnAction() {
Router::connect(
'/blog/:action/*',
array('controller' => 'blog_posts'),
Expand Down Expand Up @@ -2241,7 +2225,6 @@ public function testPassedArgsOrder() {
Router::connect('/test-passed/*', array('controller' => 'pages', 'action' => 'display', 'home'));
Router::connect('/test2/*', array('controller' => 'pages', 'action' => 'display', 2));
Router::connect('/test/*', array('controller' => 'pages', 'action' => 'display', 1));
Router::parse('/');

$result = Router::url(array('controller' => 'pages', 'action' => 'display', 1, 'whatever'));
$expected = '/test/whatever';
Expand All @@ -2267,9 +2250,17 @@ public function testRegexRouteMatching() {
$result = Router::parse('/eng/test/test_action');
$expected = array('pass' => [], 'locale' => 'eng', 'controller' => 'test', 'action' => 'test_action', 'plugin' => null);
$this->assertEquals($expected, $result);
}

$result = Router::parse('/badness/test/test_action');
$this->assertSame([], $result);
/**
* testRegexRouteMatching error
*
* @expectedException Cake\Routing\Error\MissingRouteException
* @return void
*/
public function testRegexRouteMatchingError() {
Router::connect('/:locale/:controller/:action/*', [], array('locale' => 'dan|eng'));
Router::parse('/badness/test/test_action');
}

/**
Expand Down Expand Up @@ -2304,18 +2295,6 @@ public function testRegexRouteMatchUrl() {
$this->assertEquals($expected, $result);
}

/**
* test that connectDefaults() can disable default route connection
*
* @return void
*/
public function testDefaultsMethod() {
Router::connect('/test/*', array('controller' => 'pages', 'action' => 'display', 2));
$result = Router::parse('/posts/edit/5');
$this->assertFalse(isset($result['controller']));
$this->assertFalse(isset($result['action']));
}

/**
* test that the required default routes are connected.
*
Expand Down

0 comments on commit a9ba33d

Please sign in to comment.