Skip to content

Commit a9ba33d

Browse files
committed
Throw exceptions when routes result in an error.
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.
1 parent ac16ff1 commit a9ba33d

File tree

4 files changed

+58
-47
lines changed

4 files changed

+58
-47
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
/**
3+
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
4+
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
5+
*
6+
* Licensed under The MIT License
7+
* Redistributions of files must retain the above copyright notice.
8+
*
9+
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
10+
* @link http://book.cakephp.org/2.0/en/development/testing.html
11+
* @since 3.0.0
12+
* @license http://www.opensource.org/licenses/mit-license.php MIT License
13+
*/
14+
namespace Cake\Routing\Error;
15+
16+
use Cake\Error\Exception;
17+
18+
/**
19+
* Exception raised when a URL cannot be reverse routed
20+
* or when a URL cannot be parsed.
21+
*/
22+
class MissingRouteException extends Exception {
23+
24+
protected $_messageTemplate = 'A route matching "%s" could not be found.';
25+
26+
}

src/Routing/Router.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -493,10 +493,14 @@ public static function parse($url) {
493493

494494
foreach (static::$_pathScopes as $path => $collection) {
495495
if (strpos($url, $path) === 0) {
496-
return $collection->parse($url);
496+
break;
497497
}
498498
}
499-
throw new MissingRouteException($url);
499+
$result = $collection->parse($url);
500+
if ($result) {
501+
return $result;
502+
}
503+
throw new MissingRouteException(['url' => $url]);
500504
}
501505

502506
/**
@@ -848,7 +852,7 @@ protected static function _match($url) {
848852
}
849853
}
850854

851-
throw new MissingRouteException(var_export($url, true));
855+
throw new MissingRouteException(['url' => var_export($url, true)]);
852856
}
853857

854858
/**

tests/TestCase/Controller/Component/AuthComponentTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,8 @@ public function testStatelessAuthWorksWithUser() {
979979
* @return void
980980
*/
981981
public function testComponentSettings() {
982+
Router::connect('/:controller');
983+
982984
$request = new Request();
983985
$this->Controller = new AuthTestController($request, $this->getMock('Cake\Network\Response'));
984986

tests/TestCase/Routing/RouterTest.php

Lines changed: 23 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,6 @@ public function testMapResources() {
186186
$result = Router::parse('/posts/13');
187187
$this->assertEquals($expected, $result);
188188

189-
$_SERVER['REQUEST_METHOD'] = 'GET';
190-
$result = Router::parse('/posts/add');
191-
$this->assertSame([], $result);
192-
193189
Router::reload();
194190
$result = Router::mapResources('Posts', ['id' => '[a-z0-9_]+']);
195191
$this->assertEquals(['posts'], $result);
@@ -590,7 +586,6 @@ public function testUrlGenerationBasic() {
590586

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

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

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

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

622616
Router::reload();
623617
Router::connect('/:controller/:id', array('action' => 'view'));
624-
Router::parse('/');
625618

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

635628
Router::reload();
636629
Router::connect('/:controller/:action');
637-
Router::parse('/');
638630
$request = new Request();
639631
$request->addParams(array(
640632
'action' => 'index',
@@ -652,7 +644,6 @@ public function testUrlGenerationBasic() {
652644

653645
Router::reload();
654646
Router::connect('/contact/:action', array('plugin' => 'contact', 'controller' => 'contact'));
655-
Router::parse('/');
656647

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

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

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

857845
$request = new Request();
858846
$request->addParams(array(
@@ -888,7 +876,6 @@ public function testUrlGenerationWithPrefix() {
888876
Router::setRequestInfo($request);
889877

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

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

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

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

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

958942
Router::reload();
959943
Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
960-
Router::parse('/');
961944

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

975958
Router::reload();
976959
Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
977-
Router::parse('/');
978960

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

993975
Router::reload();
994976
Router::connect('/admin/posts/*', array('controller' => 'posts', 'action' => 'index', 'prefix' => 'admin'));
995-
Router::parse('/');
996977
Router::setRequestInfo(
997978
$request->addParams(array(
998979
'plugin' => null, 'controller' => 'posts', 'action' => 'index', 'prefix' => 'admin',
@@ -1015,7 +996,6 @@ public function testUrlGenerationWithPrefix() {
1015996
public function testUrlGenerationWithExtensions() {
1016997
Router::connect('/:controller', array('action' => 'index'));
1017998
Router::connect('/:controller/:action');
1018-
Router::parse('/');
1019999

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

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

1466+
/**
1467+
* Test exceptions when parsing fails.
1468+
*
1469+
* @expectedException Cake\Routing\Error\MissingRouteException
1470+
*/
1471+
public function testParseError() {
1472+
Router::connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']);
1473+
Router::parse('/nope');
1474+
}
1475+
14871476
/**
14881477
* Test parse and reverse symmetry
14891478
*
@@ -1502,7 +1491,6 @@ public function testParseReverseSymmetry($url) {
15021491
*/
15031492
public function parseReverseSymmetryData() {
15041493
return array(
1505-
array('/'),
15061494
array('/controller/action'),
15071495
array('/controller/action/param'),
15081496
array('/controller/action?param1=value1&param2=value2'),
@@ -1559,7 +1547,6 @@ public function testPrefixRoutingAndPlugins() {
15591547
'webroot' => '/base/',
15601548
))
15611549
);
1562-
Router::parse('/');
15631550

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

1741-
Router::parse('/');
1742-
17431728
$request = new Request();
17441729
Router::setRequestInfo(
17451730
$request->addParams(array(
@@ -1863,7 +1848,6 @@ public function testPrefixRoutePersistence() {
18631848
Router::reload();
18641849
Router::connect('/protected/:controller/:action', array('prefix' => 'protected'));
18651850
Router::connect('/:controller/:action');
1866-
Router::parse('/');
18671851

18681852
$request = new Request();
18691853
Router::setRequestInfo(
@@ -2058,6 +2042,7 @@ public function testParsingWithTrailingPeriodAndParseExtensions() {
20582042
/**
20592043
* test that patterns work for :action
20602044
*
2045+
* @expectedException Cake\Routing\Error\MissingRouteException
20612046
* @return void
20622047
*/
20632048
public function testParsingWithPatternOnAction() {
@@ -2076,8 +2061,7 @@ public function testParsingWithPatternOnAction() {
20762061
);
20772062
$this->assertEquals($expected, $result);
20782063

2079-
$result = Router::parse('/blog/foobar');
2080-
$this->assertSame([], $result);
2064+
Router::parse('/blog/foobar');
20812065
}
20822066

20832067
/**
@@ -2086,7 +2070,7 @@ public function testParsingWithPatternOnAction() {
20862070
* @expectedException Cake\Routing\Error\MissingRouteException
20872071
* @return void
20882072
*/
2089-
public function testUrlPatterOnAction() {
2073+
public function testUrlPatternOnAction() {
20902074
Router::connect(
20912075
'/blog/:action/*',
20922076
array('controller' => 'blog_posts'),
@@ -2241,7 +2225,6 @@ public function testPassedArgsOrder() {
22412225
Router::connect('/test-passed/*', array('controller' => 'pages', 'action' => 'display', 'home'));
22422226
Router::connect('/test2/*', array('controller' => 'pages', 'action' => 'display', 2));
22432227
Router::connect('/test/*', array('controller' => 'pages', 'action' => 'display', 1));
2244-
Router::parse('/');
22452228

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

2271-
$result = Router::parse('/badness/test/test_action');
2272-
$this->assertSame([], $result);
2255+
/**
2256+
* testRegexRouteMatching error
2257+
*
2258+
* @expectedException Cake\Routing\Error\MissingRouteException
2259+
* @return void
2260+
*/
2261+
public function testRegexRouteMatchingError() {
2262+
Router::connect('/:locale/:controller/:action/*', [], array('locale' => 'dan|eng'));
2263+
Router::parse('/badness/test/test_action');
22732264
}
22742265

22752266
/**
@@ -2304,18 +2295,6 @@ public function testRegexRouteMatchUrl() {
23042295
$this->assertEquals($expected, $result);
23052296
}
23062297

2307-
/**
2308-
* test that connectDefaults() can disable default route connection
2309-
*
2310-
* @return void
2311-
*/
2312-
public function testDefaultsMethod() {
2313-
Router::connect('/test/*', array('controller' => 'pages', 'action' => 'display', 2));
2314-
$result = Router::parse('/posts/edit/5');
2315-
$this->assertFalse(isset($result['controller']));
2316-
$this->assertFalse(isset($result['action']));
2317-
}
2318-
23192298
/**
23202299
* test that the required default routes are connected.
23212300
*

0 commit comments

Comments
 (0)