Browse Source

Add host name matching to RouteCollection/Route

Add tests at RouteCollection layer as it is simpler/more holistic place
to test the behavior.
Mark Story 9 years ago
parent
commit
017a1f9aca
2 changed files with 90 additions and 2 deletions
  1. 5 2
      src/Routing/Route/Route.php
  2. 85 0
      tests/TestCase/Routing/RouteCollectionTest.php

+ 5 - 2
src/Routing/Route/Route.php

@@ -367,8 +367,11 @@ class Route
      */
     public function hostMatches($host)
     {
-        // Will be implemented later
-        return true;
+        if (!isset($this->options['_host'])) {
+            return true;
+        }
+        $pattern = '@^' . str_replace('\*', '.*', preg_quote($this->options['_host'], '@')) . '$@';
+        return preg_match($pattern, $host) !== 0;
     }
 
     /**

+ 85 - 0
tests/TestCase/Routing/RouteCollectionTest.php

@@ -15,6 +15,7 @@
 namespace Cake\Test\TestCase\Routing;
 
 use Cake\Http\ServerRequest;
+use Cake\Routing\Exception\MissingRouteException;
 use Cake\Routing\RouteBuilder;
 use Cake\Routing\RouteCollection;
 use Cake\Routing\Route\Route;
@@ -177,6 +178,90 @@ class RouteCollectionTest extends TestCase
     }
 
     /**
+     * Test parseRequest() checks host conditions
+     *
+     * @return void
+     */
+    public function testParseRequestCheckHostCondition()
+    {
+        $routes = new RouteBuilder($this->collection, '/');
+        $routes->connect('/fallback', ['controller' => 'Articles', 'action' => 'index'], ['_host' => '*.example.com']);
+
+        $request = new ServerRequest([
+            'environment' => [
+                'HTTP_HOST' => 'a.example.com',
+                'PATH_INFO' => '/fallback'
+            ]
+        ]);
+        $result = $this->collection->parseRequest($request);
+        $expected = [
+            'controller' => 'Articles',
+            'action' => 'index',
+            'pass' => [],
+            'plugin' => null,
+            '_matchedRoute' => '/fallback'
+        ];
+        $this->assertEquals($expected, $result, 'Should match, domain is correct');
+
+        $request = new ServerRequest([
+            'environment' => [
+                'HTTP_HOST' => 'foo.bar.example.com',
+                'PATH_INFO' => '/fallback'
+            ]
+        ]);
+        $result = $this->collection->parseRequest($request);
+        $this->assertEquals($expected, $result, 'Should match, domain is a matching subdomain');
+
+        $request = new ServerRequest([
+            'environment' => [
+                'HTTP_HOST' => 'example.test.com',
+                'PATH_INFO' => '/fallback'
+            ]
+        ]);
+        try {
+            $this->collection->parseRequest($request);
+            $this->fail('No exception raised');
+        } catch (MissingRouteException $e) {
+            $this->assertContains('/fallback', $e->getMessage());
+        }
+    }
+
+    /**
+     * Get a list of hostnames
+     *
+     * @return array
+     */
+    public static function hostProvider()
+    {
+        return [
+            ['wrong.example'],
+            ['example.com'],
+            ['aexample.com'],
+        ];
+    }
+
+    /**
+     * Test parseRequest() checks host conditions
+     *
+     * @dataProvider hostProvider
+     * @expectedException \Cake\Routing\Exception\MissingRouteException
+     * @expectedExceptionMessage A route matching "/fallback" could not be found
+     */
+    public function testParseRequestCheckHostConditionFail($host)
+    {
+        $routes = new RouteBuilder($this->collection, '/');
+        $routes->connect('/fallback', ['controller' => 'Articles', 'action' => 'index'], ['_host' => '*.example.com']);
+
+        $request = new ServerRequest([
+            'environment' => [
+                'HTTP_HOST' => $host,
+                'PATH_INFO' => '/fallback'
+            ]
+        ]);
+        $this->collection->parseRequest($request);
+    }
+
+    /**
      * Test parsing routes.
      *
      * @return void