Browse Source

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.
mark_story 11 years ago
parent
commit
a9ba33dcd5

+ 26 - 0
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.';
+
+}

+ 7 - 3
src/Routing/Router.php

@@ -493,10 +493,14 @@ class Router {
 
 		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]);
 	}
 
 /**
@@ -848,7 +852,7 @@ class Router {
 			}
 		}
 
-		throw new MissingRouteException(var_export($url, true));
+		throw new MissingRouteException(['url' => var_export($url, true)]);
 	}
 
 /**

+ 2 - 0
tests/TestCase/Controller/Component/AuthComponentTest.php

@@ -979,6 +979,8 @@ class AuthComponentTest extends TestCase {
  * @return void
  */
 	public function testComponentSettings() {
+		Router::connect('/:controller');
+
 		$request = new Request();
 		$this->Controller = new AuthTestController($request, $this->getMock('Cake\Network\Response'));
 

+ 23 - 44
tests/TestCase/Routing/RouterTest.php

@@ -186,10 +186,6 @@ class RouterTest extends TestCase {
 		$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);
@@ -590,7 +586,6 @@ class RouterTest extends TestCase {
 
 		Router::reload();
 		Router::connect('/:plugin/:id/*', array('controller' => 'posts', 'action' => 'view'), array('id' => $ID));
-		Router::parse('/');
 
 		$result = Router::url(array(
 			'plugin' => 'cake_plugin',
@@ -613,7 +608,6 @@ class RouterTest extends TestCase {
 
 		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';
@@ -621,7 +615,6 @@ class RouterTest extends TestCase {
 
 		Router::reload();
 		Router::connect('/:controller/:id', array('action' => 'view'));
-		Router::parse('/');
 
 		$result = Router::url(array('controller' => 'posts', 'action' => 'view', 'id' => '1'));
 		$expected = '/posts/1';
@@ -634,7 +627,6 @@ class RouterTest extends TestCase {
 
 		Router::reload();
 		Router::connect('/:controller/:action');
-		Router::parse('/');
 		$request = new Request();
 		$request->addParams(array(
 			'action' => 'index',
@@ -652,7 +644,6 @@ class RouterTest extends TestCase {
 
 		Router::reload();
 		Router::connect('/contact/:action', array('plugin' => 'contact', 'controller' => 'contact'));
-		Router::parse('/');
 
 		$result = Router::url(array(
 			'plugin' => 'contact',
@@ -780,7 +771,6 @@ class RouterTest extends TestCase {
 			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',
@@ -799,7 +789,6 @@ class RouterTest extends TestCase {
 			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';
@@ -852,7 +841,6 @@ class RouterTest extends TestCase {
 		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(
@@ -888,7 +876,6 @@ class RouterTest extends TestCase {
 		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';
@@ -908,7 +895,6 @@ class RouterTest extends TestCase {
 		$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';
@@ -916,7 +902,6 @@ class RouterTest extends TestCase {
 
 		Router::reload();
 		Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
-		Router::parse('/');
 		$request = new Request();
 		$request->addParams(array(
 			'plugin' => null,
@@ -935,7 +920,6 @@ class RouterTest extends TestCase {
 
 		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(
@@ -957,7 +941,6 @@ class RouterTest extends TestCase {
 
 		Router::reload();
 		Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
-		Router::parse('/');
 
 		$request = new Request();
 		Router::setRequestInfo(
@@ -974,7 +957,6 @@ class RouterTest extends TestCase {
 
 		Router::reload();
 		Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
-		Router::parse('/');
 
 		$request = new Request();
 		Router::setRequestInfo(
@@ -992,7 +974,6 @@ class RouterTest extends TestCase {
 
 		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',
@@ -1015,7 +996,6 @@ class RouterTest extends TestCase {
 	public function testUrlGenerationWithExtensions() {
 		Router::connect('/:controller', array('action' => 'index'));
 		Router::connect('/:controller/:action');
-		Router::parse('/');
 
 		$result = Router::url(array(
 			'plugin' => null,
@@ -1459,7 +1439,6 @@ class RouterTest extends TestCase {
 			array('controller' => 'pages', 'action' => 'view', 'extra' => null),
 			array("extra" => '[a-z1-9_]*', "slug" => '[a-z1-9_]+')
 		);
-		Router::parse('/');
 
 		$result = Router::url(array(
 			'admin' => null,
@@ -1485,6 +1464,16 @@ class RouterTest extends TestCase {
 	}
 
 /**
+ * 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
  *
  * @return void
@@ -1502,7 +1491,6 @@ class RouterTest extends TestCase {
  */
 	public function parseReverseSymmetryData() {
 		return array(
-			array('/'),
 			array('/controller/action'),
 			array('/controller/action/param'),
 			array('/controller/action?param1=value1&param2=value2'),
@@ -1559,7 +1547,6 @@ class RouterTest extends TestCase {
 				'webroot' => '/base/',
 			))
 		);
-		Router::parse('/');
 
 		$result = Router::url(array(
 			'plugin' => 'test_plugin',
@@ -1738,8 +1725,6 @@ class RouterTest extends TestCase {
 		Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin'));
 		Router::connect('/:controller/:action/*');
 
-		Router::parse('/');
-
 		$request = new Request();
 		Router::setRequestInfo(
 			$request->addParams(array(
@@ -1863,7 +1848,6 @@ class RouterTest extends TestCase {
 		Router::reload();
 		Router::connect('/protected/:controller/:action', array('prefix' => 'protected'));
 		Router::connect('/:controller/:action');
-		Router::parse('/');
 
 		$request = new Request();
 		Router::setRequestInfo(
@@ -2058,6 +2042,7 @@ class RouterTest extends TestCase {
 /**
  * test that patterns work for :action
  *
+ * @expectedException Cake\Routing\Error\MissingRouteException
  * @return void
  */
 	public function testParsingWithPatternOnAction() {
@@ -2076,8 +2061,7 @@ class RouterTest extends TestCase {
 		);
 		$this->assertEquals($expected, $result);
 
-		$result = Router::parse('/blog/foobar');
-		$this->assertSame([], $result);
+		Router::parse('/blog/foobar');
 	}
 
 /**
@@ -2086,7 +2070,7 @@ class RouterTest extends TestCase {
  * @expectedException Cake\Routing\Error\MissingRouteException
  * @return void
  */
-	public function testUrlPatterOnAction() {
+	public function testUrlPatternOnAction() {
 		Router::connect(
 			'/blog/:action/*',
 			array('controller' => 'blog_posts'),
@@ -2241,7 +2225,6 @@ class RouterTest extends TestCase {
 		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';
@@ -2267,9 +2250,17 @@ class RouterTest extends TestCase {
 		$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');
 	}
 
 /**
@@ -2305,18 +2296,6 @@ class RouterTest extends TestCase {
 	}
 
 /**
- * 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.
  *
  * @return void