Browse Source

Fix handling of `html` and `htm` extensions.

The `html` and `htm` extensions should be gracefully ignored, so that
the default application view rendering is being invoked.
ndm2 7 years ago
parent
commit
54be88929a

+ 4 - 8
src/Controller/Component/RequestHandlerComponent.php

@@ -332,15 +332,11 @@ class RequestHandlerComponent extends Component
         $response = $controller->getResponse();
         $request = $controller->getRequest();
 
-        $isRecognized = (
-            !in_array($this->ext, ['html', 'htm']) &&
-            $response->getMimeType($this->ext)
-        );
-        if ($this->ext && !$isRecognized) {
-            throw new NotFoundException('Invoked extension not recognized/configured: ' . $this->ext);
-        }
+        if ($this->ext && !in_array($this->ext, ['html', 'htm'])) {
+            if (!$response->getMimeType($this->ext)) {
+                throw new NotFoundException('Invoked extension not recognized/configured: ' . $this->ext);
+            }
 
-        if ($this->ext) {
             $this->renderAs($controller, $this->ext);
             $response = $controller->response;
         } else {

+ 61 - 0
tests/TestCase/Controller/Component/RequestHandlerComponentTest.php

@@ -27,6 +27,7 @@ use Cake\View\AjaxView;
 use Cake\View\JsonView;
 use Cake\View\XmlView;
 use TestApp\Controller\RequestHandlerTestController;
+use TestApp\View\AppView;
 use Zend\Diactoros\Stream;
 
 /**
@@ -442,6 +443,66 @@ class RequestHandlerComponentTest extends TestCase
     }
 
     /**
+     * @return array
+     */
+    public function defaultExtensionsProvider()
+    {
+        return [['html'], ['htm']];
+    }
+
+    /**
+     * Tests that the default extensions are using the default view.
+     *
+     * @param string $extension Extension to test.
+     * @dataProvider defaultExtensionsProvider
+     * @return void
+     */
+    public function testDefaultExtensions($extension)
+    {
+        Router::extensions([$extension], false);
+
+        $this->Controller->request = $this->Controller->request->withParam('_ext', $extension);
+        $this->RequestHandler->startup(new Event('Controller.startup', $this->Controller));
+        $this->RequestHandler->beforeRender(new Event('Controller.beforeRender', $this->Controller));
+
+        $this->assertEquals($extension, $this->RequestHandler->ext);
+        $this->assertEquals('text/html', $this->Controller->response->getType());
+
+        $view = $this->Controller->createView();
+        $this->assertInstanceOf(AppView::class, $view);
+        $this->assertEmpty($view->getLayoutPath());
+        $this->assertEmpty($view->getSubDir());
+    }
+
+    /**
+     * Tests that the default extensions can be overwritten by the accept header.
+     *
+     * @param string $extension Extension to test.
+     * @dataProvider defaultExtensionsProvider
+     * @return void
+     */
+    public function testDefaultExtensionsOverwrittenByAcceptHeader($extension)
+    {
+        Router::extensions([$extension], false);
+
+        $this->Controller->request = $this->request->withHeader(
+            'Accept',
+            'application/xml'
+        );
+        $this->Controller->request = $this->Controller->request->withParam('_ext', $extension);
+        $this->RequestHandler->startup(new Event('Controller.startup', $this->Controller));
+        $this->RequestHandler->beforeRender(new Event('Controller.beforeRender', $this->Controller));
+
+        $this->assertEquals('xml', $this->RequestHandler->ext);
+        $this->assertEquals('application/xml', $this->Controller->response->getType());
+
+        $view = $this->Controller->createView();
+        $this->assertInstanceOf(XmlView::class, $view);
+        $this->assertEquals('xml', $view->getLayoutPath());
+        $this->assertEquals('xml', $view->getSubDir());
+    }
+
+    /**
      * test custom JsonView class is loaded and correct.
      *
      * @return void