Project

General

Profile

Actions

Bug #103215

open

PageContentErrorHandler attaches error output to current response's output instead of replacing it.

Added by Sven Proffe 2 months ago. Updated 26 days ago.

Status:
New
Priority:
Must have
Assignee:
-
Category:
-
Target version:
-
Start date:
2024-02-27
Due date:
% Done:

0%

Estimated time:
TYPO3 Version:
12
PHP Version:
8.3
Tags:
Complexity:
Is Regression:
Sprint Focus:

Description

When a non-cacheable plugin throws a PropagateResponseException with the response of TYPO3\CMS\Frontend\Controller\ErrorController->pageNotFoundAction(), this response gets attached to the output of the originally requested page.

Background:
Since TYPO3 v12 TYPO3\CMS\Core\Error\PageErrorHandler\PageContentErrorHandler uses a sub-request to render and fetch the content of the configured 404 page. In earlier versions of TYPO3 this was done with a curl request. TYPO3 v11 introduced an experimental and optional feature to use a sub-request (feature: #94402), which was set as standard behaviour within TYPO3 v12 (https://forge.typo3.org/issues/98396).

Problem:
Though the sub-request to fetch the 404 content is done as a new request, the underlying TYPO3\CMS\Core\Page\PageRenderer is a singleton. So, it still holds the already rendered (HTML) output of the original request in its property $bodyContent. During the process of rendering the sub-request, the content of the 404 page is then only added to this content. What is even more annoying: This faulty 404 content will be cached and then delivered whenever a 404 error occurs.

Proposed solution:
Before sending the sub-request, PageContentErrorHandler should clear PageRenderer->bodyContent to make sure only the output of the 404 page is rendered. Perhaps like so:

protected function sendSubRequest(ServerRequestInterface $request, int $pageId, ServerRequestInterface $originalRequest): ResponseInterface
{
    $site = $request->getAttribute('site');
    if (!$site instanceof Site) {
        $site = $this->siteFinder->getSiteByPageId($pageId);
        $request = $request->withAttribute('site', $site);
    }

    $request = $request->withAttribute('originalRequest', $originalRequest);

    // Reset already rendered content of the original request/response
    $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
    $pageRenderer->setBodyContent('');

    return $this->application->handle($request);
}

Another possible solution would be to reset the entire singleton instance of PageRenderer via GeneralUtility::removeSingletonInstance().

To reproduce this problem:

1. Have a non-cacheable (!) Extbase plugin that throws an Exception like this (FQDN only for not being ambiguous):

public function pageNotFoundAction(): ResponseInterface
{
    $errorController = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Frontend\Controller\ErrorController\ErrorController::class);
    $response = $errorController->pageNotFoundAction(
        $GLOBALS['TYPO3_REQUEST'],
        'Content unavailable',
        [
            'code' => \TYPO3\CMS\Frontend\Page\PageAccessFailureReasons\PageAccessFailureReasons::PAGE_NOT_FOUND,
        ]
    );
    throw new \TYPO3\CMS\Core\Http\PropagateResponseException\PropagateResponseException($response);

    return $this->htmlResponse();
}

2. Place that plugin on a page

3. Inside your site config have a page based error handling for 404 errors like so

errorHandling:
  -
    errorCode: 404
    errorHandler: Page
    errorContentSource: 't3://page?uid=xxxx'

3. Make sure the entire TYPO3 cache has been cleared

4. Request the page containing the plugin with a client


Related issues 1 (0 open1 closed)

Related to TYPO3 Core - Task #98396: Enable internal subrequests for error pages by defaultClosed2022-09-21

Actions
Actions #1

Updated by Christian Weiske 26 days ago · Edited

I see this in TYPO3 12.4.13 with PHP 8.2.

I can confirm that the proposed solution ("Reset already rendered content of the original request/response") works.

Actions #2

Updated by Christian Weiske 26 days ago

  • Related to Task #98396: Enable internal subrequests for error pages by default added
Actions

Also available in: Atom PDF