[BUGFIX] Avoid exception on non-existing error handler 77/57877/6
authorBenni Mack <benni@typo3.org>
Sat, 11 Aug 2018 18:41:37 +0000 (20:41 +0200)
committerWouter Wolters <typo3@wouterwolters.nl>
Sun, 12 Aug 2018 12:21:56 +0000 (14:21 +0200)
When a site is configured, but has no error handler
for a specific error case (e.g. a site has no
configured 404 page), then the regular error handler
should kick in.

This also allows to enable some previously wrong
tests (expected!).

Resolves: #85819
Releases: master
Change-Id: Iefc0e23460de0389b66083da4e6d7aca12b82c59
Reviewed-on: https://review.typo3.org/57877
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Andreas Wolf <andreas.wolf@typo3.org>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Tested-by: Wouter Wolters <typo3@wouterwolters.nl>
typo3/sysext/core/Classes/Error/PageErrorHandler/PageErrorHandlerNotConfiguredException.php [new file with mode: 0644]
typo3/sysext/core/Classes/Site/Entity/Site.php
typo3/sysext/core/Classes/Site/Entity/SiteInterface.php
typo3/sysext/core/Tests/Unit/Site/Entity/SiteTest.php
typo3/sysext/frontend/Classes/Controller/ErrorController.php
typo3/sysext/frontend/Tests/Functional/SiteHandling/SiteRequestTest.php

diff --git a/typo3/sysext/core/Classes/Error/PageErrorHandler/PageErrorHandlerNotConfiguredException.php b/typo3/sysext/core/Classes/Error/PageErrorHandler/PageErrorHandlerNotConfiguredException.php
new file mode 100644 (file)
index 0000000..0df788a
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+declare(strict_types = 1);
+
+namespace TYPO3\CMS\Core\Error\PageErrorHandler;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Core\Error\Exception;
+
+/**
+ * Is typically used, when a site configuration has no page-error handler configured
+ * for a specific HTTP Status type that is requested.
+ */
+class PageErrorHandlerNotConfiguredException extends Exception
+{
+}
index cdbcc89..1eefcb4 100644 (file)
@@ -20,6 +20,7 @@ use TYPO3\CMS\Core\Error\PageErrorHandler\FluidPageErrorHandler;
 use TYPO3\CMS\Core\Error\PageErrorHandler\InvalidPageErrorHandlerException;
 use TYPO3\CMS\Core\Error\PageErrorHandler\PageContentErrorHandler;
 use TYPO3\CMS\Core\Error\PageErrorHandler\PageErrorHandlerInterface;
+use TYPO3\CMS\Core\Error\PageErrorHandler\PageErrorHandlerNotConfiguredException;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -184,7 +185,7 @@ class Site implements SiteInterface
      *
      * @param int $statusCode
      * @return PageErrorHandlerInterface
-     * @throws \RuntimeException
+     * @throws PageErrorHandlerNotConfiguredException
      * @throws InvalidPageErrorHandlerException
      */
     public function getErrorHandler(int $statusCode): PageErrorHandlerInterface
@@ -203,7 +204,7 @@ class Site implements SiteInterface
                 }
                 return $handler;
         }
-        throw new \RuntimeException('No error handler given for the status code "' . $statusCode . '".', 1522495914);
+        throw new PageErrorHandlerNotConfiguredException('No error handler given for the status code "' . $statusCode . '".', 1522495914);
     }
 
     /**
index 26f18e0..11a0ac9 100644 (file)
@@ -17,6 +17,7 @@ namespace TYPO3\CMS\Core\Site\Entity;
  */
 
 use TYPO3\CMS\Core\Error\PageErrorHandler\PageErrorHandlerInterface;
+use TYPO3\CMS\Core\Error\PageErrorHandler\PageErrorHandlerNotConfiguredException;
 
 interface SiteInterface
 {
@@ -48,7 +49,7 @@ interface SiteInterface
      *
      * @param int $statusCode
      * @return PageErrorHandlerInterface
-     * @throws \RuntimeException
+     * @throws PageErrorHandlerNotConfiguredException
      */
     public function getErrorHandler(int $statusCode): PageErrorHandlerInterface;
 }
index c3abe54..cd0916b 100644 (file)
@@ -21,6 +21,7 @@ use TYPO3\CMS\Core\Error\PageErrorHandler\FluidPageErrorHandler;
 use TYPO3\CMS\Core\Error\PageErrorHandler\InvalidPageErrorHandlerException;
 use TYPO3\CMS\Core\Error\PageErrorHandler\PageContentErrorHandler;
 use TYPO3\CMS\Core\Error\PageErrorHandler\PageErrorHandlerInterface;
+use TYPO3\CMS\Core\Error\PageErrorHandler\PageErrorHandlerNotConfiguredException;
 use TYPO3\CMS\Core\Site\Entity\Site;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
@@ -181,7 +182,7 @@ class SiteTest extends UnitTestCase
      */
     public function getErrorHandlerThrowsExceptionWhenNoErrorHandlerIsConfigured()
     {
-        $this->expectException(\RuntimeException::class);
+        $this->expectException(PageErrorHandlerNotConfiguredException::class);
         $this->expectExceptionCode(1522495914);
         $this->expectExceptionMessage('No error handler given for the status code "404".');
         $subject = new Site('aint-misbehaving', 13, ['languages' => []]);
@@ -193,7 +194,7 @@ class SiteTest extends UnitTestCase
      */
     public function getErrorHandlerThrowsExceptionWhenNoErrorHandlerForStatusCodeIsConfigured()
     {
-        $this->expectException(\RuntimeException::class);
+        $this->expectException(PageErrorHandlerNotConfiguredException::class);
         $this->expectExceptionCode(1522495914);
         $this->expectExceptionMessage('No error handler given for the status code "404".');
         $subject = new Site('aint-misbehaving', 13, [
index 8b8aea1..55a0244 100644 (file)
@@ -21,6 +21,7 @@ use TYPO3\CMS\Core\Controller\ErrorPageController;
 use TYPO3\CMS\Core\Error\Http\PageNotFoundException;
 use TYPO3\CMS\Core\Error\Http\ServiceUnavailableException;
 use TYPO3\CMS\Core\Error\PageErrorHandler\PageErrorHandlerInterface;
+use TYPO3\CMS\Core\Error\PageErrorHandler\PageErrorHandlerNotConfiguredException;
 use TYPO3\CMS\Core\Http\HtmlResponse;
 use TYPO3\CMS\Core\Http\RedirectResponse;
 use TYPO3\CMS\Core\Site\Entity\Site;
@@ -307,6 +308,13 @@ class ErrorController
     protected function getErrorHandlerFromSite(ServerRequestInterface $request, int $statusCode): ?PageErrorHandlerInterface
     {
         $site = $request->getAttribute('site');
-        return $site instanceof Site ? $site->getErrorHandler($statusCode) : $site;
+        if ($site instanceof Site) {
+            try {
+                return $site->getErrorHandler($statusCode);
+            } catch (PageErrorHandlerNotConfiguredException $e) {
+                // No error handler found, so fallback back to the generic TYPO3 error handler.
+            }
+        }
+        return null;
     }
 }
index e997737..05f7ca1 100644 (file)
@@ -17,6 +17,7 @@ namespace TYPO3\CMS\Frontend\Tests\Functional\SiteHandling;
 
 use TYPO3\CMS\Core\Configuration\SiteConfiguration;
 use TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\Error\Http\PageNotFoundException;
 use TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\Fixtures\PhpError;
 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\ActionService;
 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataMapFactory;
@@ -335,8 +336,6 @@ class SiteRequestTest extends AbstractRequestTest
      *
      * @test
      * @dataProvider pageRenderingStopsWithInvalidCacheHashDataProvider
-     * @todo In case no error handler is defined, default handler should be used
-     * @see PlainRequestTest::pageRequestSendsNotFoundResponseWithInvalidCacheHash
      */
     public function pageRequestThrowsExceptionWithInvalidCacheHashWithoutHavingErrorHandling(string $uri)
     {
@@ -345,8 +344,8 @@ class SiteRequestTest extends AbstractRequestTest
             $this->buildSiteConfiguration(101, 'https://website.local/')
         );
 
-        $this->expectExceptionCode(1522495914);
-        $this->expectException(\RuntimeException::class);
+        $this->expectExceptionCode(1518472189);
+        $this->expectException(PageNotFoundException::class);
 
         $this->executeFrontendRequest(
             new InternalRequest($uri),
@@ -360,6 +359,38 @@ class SiteRequestTest extends AbstractRequestTest
      * @test
      * @dataProvider pageRenderingStopsWithInvalidCacheHashDataProvider
      */
+    public function pageRequestSendsNotFoundResponseWithInvalidCacheHash(string $uri)
+    {
+        $response = $this->executeFrontendRequest(
+            new InternalRequest($uri),
+            $this->internalRequestContext->withMergedGlobalSettings([
+                'TYPO3_CONF_VARS' => [
+                    'FE' => [
+                        'pageNotFound_handling' => 'READFILE:typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/PageError.txt',
+                    ]
+                ]
+            ])
+        );
+
+        static::assertSame(
+            404,
+            $response->getStatusCode()
+        );
+        static::assertThat(
+            (string)$response->getBody(),
+            static::logicalOr(
+                static::stringContains('reason: Request parameters could not be validated (&amp;cHash empty)'),
+                static::stringContains('reason: Request parameters could not be validated (&amp;cHash comparison failed)')
+            )
+        );
+    }
+
+    /**
+     * @param string $uri
+     *
+     * @test
+     * @dataProvider pageRenderingStopsWithInvalidCacheHashDataProvider
+     */
     public function pageRequestSendsNotFoundResponseWithInvalidCacheHashWithHavingFluidErrorHandling(string $uri)
     {
         $this->writeSiteConfiguration(