diff --git a/typo3/sysext/core/Classes/Error/PageErrorHandler/PageContentErrorHandler.php b/typo3/sysext/core/Classes/Error/PageErrorHandler/PageContentErrorHandler.php index c58510c83ffdc17a2680e99a344f13b9748075cd..7935b59054724dc79bf1476b73bbb076d5a23599 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 abd83d06d198f8c618046d0a56ce18bf08a8031b..0000000000000000000000000000000000000000 --- 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