Browse Source

Handle host & scheme in array URLs

When handling array URLs or absolute URLs IntegrationTestCase should
forward https and host data to the right place. I was able to replace
our URL parsing logic with the Uri implementation from diactoros letting
us save a few cycles in each test method.

Fixes #13204
Mark Story 6 years ago
parent
commit
fed498ecf3

+ 19 - 12
src/TestSuite/IntegrationTestTrait.php

@@ -53,6 +53,7 @@ use Cake\Utility\Hash;
 use Cake\Utility\Security;
 use Cake\Utility\Text;
 use Cake\View\Helper\SecureFieldTokenTrait;
+use Zend\Diactoros\Uri;
 use Exception;
 use LogicException;
 use PHPUnit\Exception as PhpunitException;
@@ -610,7 +611,7 @@ trait IntegrationTestTrait
         ];
         $session = Session::create($sessionConfig);
         $session->write($this->_session);
-        list($url, $query) = $this->_url($url);
+        list($url, $query, $hostInfo) = $this->_url($url);
         $tokenUrl = $url;
 
         if ($query) {
@@ -638,6 +639,12 @@ trait IntegrationTestTrait
             'QUERY_STRING' => $query,
             'REQUEST_URI' => $url,
         ];
+        if (!empty($hostInfo['ssl'])) {
+            $env['HTTPS'] = 'on';
+        }
+        if (isset($hostInfo['host'])) {
+            $env['HTTP_HOST'] = $hostInfo['host'];
+        }
         if (isset($this->_request['headers'])) {
             foreach ($this->_request['headers'] as $k => $v) {
                 $name = strtoupper(str_replace('-', '_', $k));
@@ -717,23 +724,23 @@ trait IntegrationTestTrait
      * Creates a valid request url and parameter array more like Request::_url()
      *
      * @param string|array $url The URL
-     * @return array Qualified URL and the query parameters
+     * @return array Qualified URL, the query parameters, and host data
      */
     protected function _url($url)
     {
-        // re-create URL in ServerRequest's context so
-        // query strings are encoded as expected
-        $request = new ServerRequest(['url' => $url]);
-        $url = $request->getRequestTarget();
+        $uri = new Uri($url);
+        $path = $uri->getPath();
+        $query = $uri->getQuery();
 
-        $query = '';
-
-        $path = parse_url($url, PHP_URL_PATH);
-        if (strpos($url, '?') !== false) {
-            $query = parse_url($url, PHP_URL_QUERY);
+        $hostData = [];
+        if ($uri->getHost()) {
+            $hostData['host'] = $uri->getHost();
+        }
+        if ($uri->getScheme()) {
+            $hostData['ssl'] = $uri->getScheme() === 'https';
         }
 
-        return [$path, $query];
+        return [$path, $query, $hostData];
     }
 
     /**

+ 20 - 1
tests/TestCase/TestSuite/IntegrationTestTraitTest.php

@@ -308,7 +308,7 @@ class IntegrationTestTraitTest extends IntegrationTestCase
      */
     public function testGetUsingApplicationWithDefaultRoutes()
     {
-        // first clean routes to have Router::$initailized === false
+        // first clean routes to have Router::$initialized === false
         Router::reload();
 
         $this->configApplication(Configure::read('App.namespace') . '\ApplicationWithDefaultRoutes', null);
@@ -685,6 +685,25 @@ class IntegrationTestTraitTest extends IntegrationTestCase
     }
 
     /**
+     * Test array URL with host
+     *
+     * @return void
+     */
+    public function testArrayUrlWithHost()
+    {
+        $this->useHttpServer(true);
+        $this->get([
+            'controller' => 'Posts',
+            'action' => 'hostData',
+            '_host' => 'app.example.org',
+            '_ssl' => true,
+        ]);
+        $this->assertResponseOk();
+        $this->assertResponseContains('"isSsl":true');
+        $this->assertResponseContains('"host":"app.example.org"');
+    }
+
+    /**
      * Test array URLs with an empty router.
      *
      * @return void

+ 12 - 0
tests/test_app/TestApp/Controller/PostsController.php

@@ -116,6 +116,18 @@ class PostsController extends AppController
         return $this->getResponse()->withHeader('X-Cake', 'custom header');
     }
 
+    public function hostData()
+    {
+        $data = [
+            'host' => $this->request->host(),
+            'isSsl' => $this->request->is('ssl'),
+        ];
+
+        debug($data);
+
+        return $this->getResponse()->withStringBody(json_encode($data));
+    }
+
     public function empty_response()
     {
         return $this->getResponse()->withStringBody('');