[TASK] Move redirect to shortcut and mount point to middleware 86/56886/2
authorHelmut Hummel <typo3@helhum.io>
Tue, 1 May 2018 16:56:05 +0000 (18:56 +0200)
committerBenni Mack <benni@typo3.org>
Thu, 10 May 2018 09:58:04 +0000 (11:58 +0200)
Instead of using HttpUtility to redirect and exit the program
flow, we now return a proper redirect response in a middleware.

Resolves: #84946
Releases: master
Change-Id: I397790ea1d46ae46ef41bd9c2f03f3aac079d1a4
Reviewed-on: https://review.typo3.org/56886
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Mathias Schreiber <mathias.schreiber@typo3.com>
Tested-by: Mathias Schreiber <mathias.schreiber@typo3.com>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php
typo3/sysext/frontend/Classes/Http/RequestHandler.php
typo3/sysext/frontend/Classes/Middleware/ShortcutAndMountPointRedirect.php [new file with mode: 0644]
typo3/sysext/frontend/Configuration/RequestMiddlewares.php

index 67b8078..91da397 100644 (file)
@@ -2955,37 +2955,88 @@ class TypoScriptFrontendController implements LoggerAwareInterface
     }
 
     /**
+     * Returns URI of target page, if the current page is an overlaid mountpoint.
+     *
+     * If the current page is of type mountpoint and should be overlaid with the contents of the mountpoint page
+     * and is accessed directly, the user will be redirected to the mountpoint context.
+     * @internal
+     */
+    public function getRedirectUriForMountPoint(): ?string
+    {
+        if (!empty($this->originalMountPointPage) && (int)$this->originalMountPointPage['doktype'] === PageRepository::DOKTYPE_MOUNTPOINT) {
+            return $this->getUriToCurrentPageForRedirect();
+        }
+
+        return null;
+    }
+
+    /**
      * Redirect to target page if the current page is an overlaid mountpoint.
      *
      * If the current page is of type mountpoint and should be overlaid with the contents of the mountpoint page
      * and is accessed directly, the user will be redirected to the mountpoint context.
+     * @deprecated in TYPO3 9, will be removed in TYPO3 10
      */
     public function checkPageForMountpointRedirect()
     {
+        trigger_error('Method ' . __FUNCTION__ . 'is deprecated.', \E_USER_DEPRECATED);
         if (!empty($this->originalMountPointPage) && $this->originalMountPointPage['doktype'] == PageRepository::DOKTYPE_MOUNTPOINT) {
             $this->redirectToCurrentPage();
         }
     }
 
     /**
+     * Returns URI of target page, if the current page is a Shortcut.
+     *
+     * If the current page is of type shortcut and accessed directly via its URL,
+     * the user will be redirected to shortcut target.
+     * @internal
+     */
+    public function getRedirectUriForShortcut(): ?string
+    {
+        if (!empty($this->originalShortcutPage) && $this->originalShortcutPage['doktype'] == PageRepository::DOKTYPE_SHORTCUT) {
+            return $this->getUriToCurrentPageForRedirect();
+        }
+
+        return null;
+    }
+
+    /**
      * Redirect to target page, if the current page is a Shortcut.
      *
      * If the current page is of type shortcut and accessed directly via its URL, this function redirects to the
      * Shortcut target using a Location header.
+     * @deprecated in TYPO3 9, will be removed in TYPO3 10
      */
     public function checkPageForShortcutRedirect()
     {
-        if (!empty($this->originalShortcutPage) && $this->originalShortcutPage['doktype'] == PageRepository::DOKTYPE_SHORTCUT) {
+        trigger_error('Method ' . __FUNCTION__ . 'is deprecated.', \E_USER_DEPRECATED);
+        if (!empty($this->originalShortcutPage) && (int)$this->originalShortcutPage['doktype'] === PageRepository::DOKTYPE_SHORTCUT) {
             $this->redirectToCurrentPage();
         }
     }
 
     /**
-     * Builds a typolink to the current page, appends the type paremeter if required
+     * Builds a typolink to the current page, appends the type parameter if required
      * and redirects the user to the generated URL using a Location header.
+     * @deprecated in TYPO3 9, will be removed in TYPO3 10
      */
     protected function redirectToCurrentPage()
     {
+        trigger_error('Method ' . __FUNCTION__ . 'is deprecated.', \E_USER_DEPRECATED);
+        $redirectUrl = $this->getUriToCurrentPageForRedirect();
+        // Prevent redirection loop
+        if (!empty($redirectUrl) && GeneralUtility::getIndpEnv('REQUEST_URI') !== '/' . $redirectUrl) {
+            // redirect and exit
+            HttpUtility::redirect($redirectUrl, HttpUtility::HTTP_STATUS_307);
+        }
+    }
+
+    /**
+     * @return string
+     */
+    protected function getUriToCurrentPageForRedirect(): string
+    {
         $this->calculateLinkVars();
         // Instantiate \TYPO3\CMS\Frontend\ContentObject to generate the correct target URL
         /** @var $cObj ContentObjectRenderer */
@@ -2995,14 +3046,12 @@ class TypoScriptFrontendController implements LoggerAwareInterface
         if ($type && MathUtility::canBeInterpretedAsInteger($type)) {
             $parameter .= ',' . $type;
         }
-        $redirectUrl = $cObj->typoLink_URL(['parameter' => $parameter, 'addQueryString' => true,
-            'addQueryString.' => ['exclude' => 'id']]);
-
-        // Prevent redirection loop
-        if (!empty($redirectUrl) && GeneralUtility::getIndpEnv('REQUEST_URI') !== '/' . $redirectUrl) {
-            // redirect and exit
-            HttpUtility::redirect($redirectUrl, HttpUtility::HTTP_STATUS_307);
-        }
+        $redirectUrl = $cObj->typoLink_URL([
+            'parameter' => $parameter,
+            'addQueryString' => true,
+            'addQueryString.' => ['exclude' => 'id']
+        ]);
+        return $redirectUrl;
     }
 
     /********************************************
index 604b85b..361cc67 100644 (file)
@@ -68,10 +68,6 @@ class RequestHandler implements RequestHandlerInterface, PsrRequestHandlerInterf
         /** @var TypoScriptFrontendController $controller */
         $controller = $GLOBALS['TSFE'];
 
-        // Check for shortcut page and redirect
-        $controller->checkPageForShortcutRedirect();
-        $controller->checkPageForMountpointRedirect();
-
         // Generate page
         $controller->setUrlIdToken();
         if ($controller->isGeneratePage()) {
diff --git a/typo3/sysext/frontend/Classes/Middleware/ShortcutAndMountPointRedirect.php b/typo3/sysext/frontend/Classes/Middleware/ShortcutAndMountPointRedirect.php
new file mode 100644 (file)
index 0000000..fae8894
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+declare(strict_types = 1);
+namespace TYPO3\CMS\Frontend\Middleware;
+
+/*
+ * 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 Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\MiddlewareInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+use TYPO3\CMS\Core\Http\RedirectResponse;
+use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
+
+/**
+ * Checks mount points or shortcuts and redirects to the target
+ */
+class ShortcutAndMountPointRedirect implements MiddlewareInterface
+{
+    /**
+     * @var TypoScriptFrontendController
+     */
+    private $controller;
+
+    public function __construct(TypoScriptFrontendController $controller = null)
+    {
+        $this->controller = $controller ?: $GLOBALS['TSFE'];
+    }
+
+    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
+    {
+        // Check for shortcut page and mount point redirect
+        $redirectToUri = $this->getRedirectUri();
+        if ($redirectToUri !== null && $redirectToUri !== (string)$request->getUri()) {
+            return new RedirectResponse($redirectToUri, 307);
+        }
+
+        return $handler->handle($request);
+    }
+
+    protected function getRedirectUri(): ?string
+    {
+        $redirectToUri = $this->controller->getRedirectUriForShortcut();
+        if ($redirectToUri !== null) {
+            return $redirectToUri;
+        }
+        return $this->controller->getRedirectUriForMountPoint();
+    }
+}
index 4912d28..dfab932 100644 (file)
@@ -96,5 +96,14 @@ return [
                 'typo3/cms-frontend/page-resolver',
             ]
         ],
+        'typo3/cms-frontend/shortcut-and-mountpoint-redirect' => [
+            'target' => \TYPO3\CMS\Frontend\Middleware\ShortcutAndMountPointRedirect::class,
+            'after' => [
+                'typo3/cms-frontend/prepare-tsfe-rendering',
+            ],
+            'before' => [
+                'typo3/cms-frontend/content-length-headers',
+            ],
+        ],
     ]
 ];