From 5aea1b2e488222e8b446151197597f3682cf0aa8 Mon Sep 17 00:00:00 2001 From: Susanne Moog <look@susi.dev> Date: Mon, 24 Feb 2020 19:19:21 +0100 Subject: [PATCH] Revert "[FEATURE] Allow PageContentErrorHandler to resolve pages with sub requests" This reverts commit a848ba4f2798105d86537ae7b1185f661d29bd3d. While the feature works well on fully configured sites, in case of errors this is currently too unstable and may result in infinite recursions when a page is not configured (for example if no TS Template is present). When reimplementing we should add more tests and recursion prevention in order to stabilize the behaviour. Change-Id: I9f6f5155a78e7d515107f8b6b8d16dc55b78b7dd Resolves: #90523 Releases: master Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/63308 Tested-by: TYPO3com <noreply@typo3.com> Tested-by: Georg Ringer <georg.ringer@gmail.com> Reviewed-by: Georg Ringer <georg.ringer@gmail.com> --- .../PageContentErrorHandler.php | 105 +++++++----------- ...lerResolveInternalPagesWithSubRequests.rst | 23 ---- 2 files changed, 40 insertions(+), 88 deletions(-) delete mode 100644 typo3/sysext/core/Documentation/Changelog/master/Feature-90505-MakePageContentErrorHandlerResolveInternalPagesWithSubRequests.rst diff --git a/typo3/sysext/core/Classes/Error/PageErrorHandler/PageContentErrorHandler.php b/typo3/sysext/core/Classes/Error/PageErrorHandler/PageContentErrorHandler.php index c58510c83ffd..7935b5905472 100644 --- a/typo3/sysext/core/Classes/Error/PageErrorHandler/PageContentErrorHandler.php +++ b/typo3/sysext/core/Classes/Error/PageErrorHandler/PageContentErrorHandler.php @@ -18,19 +18,14 @@ namespace TYPO3\CMS\Core\Error\PageErrorHandler; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use TYPO3\CMS\Core\Cache\CacheManager; -use TYPO3\CMS\Core\DependencyInjection\FailsafeContainer; use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\Http\HtmlResponse; -use TYPO3\CMS\Core\Http\MiddlewareDispatcher; -use TYPO3\CMS\Core\Http\MiddlewareStackResolver; use TYPO3\CMS\Core\LinkHandling\LinkService; use TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException; -use TYPO3\CMS\Core\Service\DependencyOrderingService; use TYPO3\CMS\Core\Site\Entity\Site; +use TYPO3\CMS\Core\Site\Entity\SiteLanguage; use TYPO3\CMS\Core\Site\SiteFinder; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Frontend\Http\RequestHandler; /** * Renders the content of a page to be displayed (also in relation to language etc) @@ -73,20 +68,8 @@ class PageContentErrorHandler implements PageErrorHandlerInterface */ public function handlePageError(ServerRequestInterface $request, string $message, array $reasons = []): ResponseInterface { - $linkService = GeneralUtility::makeInstance(LinkService::class); - $urlParams = $linkService->resolve((string)$this->errorHandlerConfiguration['errorContentSource']); - - if ($urlParams['type'] !== 'page' && $urlParams['type'] !== 'url') { - throw new \InvalidArgumentException('PageContentErrorHandler can only handle TYPO3 urls of types "page" or "url"', 1522826609); - } - - if ($urlParams['type'] === 'page') { - $response = $this->buildSubRequest($request, (int)$urlParams['pageuid']); - return $response->withStatus($this->statusCode); - } - - $resolvedUrl = $urlParams['url']; try { + $resolvedUrl = $this->resolveUrl($request, $this->errorHandlerConfiguration['errorContentSource']); $content = null; $report = []; @@ -99,67 +82,59 @@ class PageContentErrorHandler implements PageErrorHandlerInterface } catch (InvalidRouteArgumentsException | SiteNotFoundException $e) { $content = 'Invalid error handler configuration: ' . $this->errorHandlerConfiguration['errorContentSource']; } - return new HtmlResponse($content, $this->statusCode); } /** + * Resolve the URL (currently only page and external URL are supported) + * * @param ServerRequestInterface $request - * @param int $pageId - * @return ResponseInterface + * @param string $typoLinkUrl + * @return string * @throws SiteNotFoundException - * @throws \TYPO3\CMS\Core\Cache\Exception\InvalidDataException - * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException - * @throws \TYPO3\CMS\Core\Exception - * @throws \RuntimeException + * @throws InvalidRouteArgumentsException */ - protected function buildSubRequest(ServerRequestInterface $request, int $pageId): ResponseInterface + protected function resolveUrl(ServerRequestInterface $request, string $typoLinkUrl): string { + $linkService = GeneralUtility::makeInstance(LinkService::class); + $urlParams = $linkService->resolve($typoLinkUrl); + if ($urlParams['type'] !== 'page' && $urlParams['type'] !== 'url') { + throw new \InvalidArgumentException('PageContentErrorHandler can only handle TYPO3 urls of types "page" or "url"', 1522826609); + } + if ($urlParams['type'] === 'url') { + return $urlParams['url']; + } + $site = $request->getAttribute('site', null); if (!$site instanceof Site) { - $site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($pageId); - $request = $request->withAttribute('site', $site); + $site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId((int)$urlParams['pageuid']); } - - if (!$this->pageExistsAndInRootline($pageId, $site->getRootPageId())) { - throw new \RuntimeException('Page does not exist or is not in rootline.', 1582448967); + $language = $request->getAttribute('language', null); + if (!$language instanceof SiteLanguage || !$language->isEnabled()) { + $language = $site->getDefaultLanguage(); } - $request = $request->withQueryParams(['id' => $pageId]); - $dispatcher = $this->buildDispatcher(); - return $dispatcher->handle($request); - } - - /** - * @return MiddlewareDispatcher - * @throws \TYPO3\CMS\Core\Cache\Exception\InvalidDataException - * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException - * @throws \TYPO3\CMS\Core\Exception - */ - protected function buildDispatcher() - { - $requestHandler = GeneralUtility::makeInstance(RequestHandler::class); - $resolver = new MiddlewareStackResolver( - GeneralUtility::makeInstance(FailsafeContainer::class), - GeneralUtility::makeInstance(DependencyOrderingService::class), - GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_core') + // Build Url + $uri = $site->getRouter()->generateUri( + (int)$urlParams['pageuid'], + ['_language' => $language] ); - $middlewares = $resolver->resolve('frontend'); - return new MiddlewareDispatcher($requestHandler, $middlewares); - } - - /** - * @param int $pageId - * @param int $rootPageId - * @return bool - */ - protected function pageExistsAndInRootline(int $pageId, int $rootPageId): bool - { - try { - return GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($pageId)->getRootPageId() === $rootPageId; - } catch (SiteNotFoundException $e) { - return false; + // Fallback to the current URL if the site is not having a proper scheme and host + $currentUri = $request->getUri(); + if (empty($uri->getScheme())) { + $uri = $uri->withScheme($currentUri->getScheme()); } + if (empty($uri->getUserInfo())) { + $uri = $uri->withUserInfo($currentUri->getUserInfo()); + } + if (empty($uri->getHost())) { + $uri = $uri->withHost($currentUri->getHost()); + } + if ($uri->getPort() === null) { + $uri = $uri->withPort($currentUri->getPort()); + } + + return (string)$uri; } } diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-90505-MakePageContentErrorHandlerResolveInternalPagesWithSubRequests.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-90505-MakePageContentErrorHandlerResolveInternalPagesWithSubRequests.rst deleted file mode 100644 index abd83d06d198..000000000000 --- a/typo3/sysext/core/Documentation/Changelog/master/Feature-90505-MakePageContentErrorHandlerResolveInternalPagesWithSubRequests.rst +++ /dev/null @@ -1,23 +0,0 @@ -.. include:: ../../Includes.txt - -=========================================================================================== -Feature: #90505 - Allow PageContentErrorHandler to resolve internal pages with sub requests -=========================================================================================== - -See :issue:`90505` - -Description -=========== - -The PageContentErrorHandler provided by the core can take in either a URL or a page uid for resolving an error page in the frontend. In both cases, the class would then start a Guzzle/cURL request to fetch the error page content. -This has now been changed for internal pages, where a page uid has been given. In this case, the PageContentErrorHandler will now dispatch an internal SubRequest instead, to avoid an unnecessary cURL call. - - -Impact -====== - -In staging environments, the website would often be access protected with basic auth options (for example a .htpasswd auth file on Apache Webservers). -In such a case, error pages with the default PageContentErrorHandler would have failed before, as the internal cURL call for fetching the error page was lacking these required basic auth options. -For internal pages, a sub request is now used, bypassing the need for an external cURL call. - -.. index:: Frontend, ext:core -- GitLab