4954edb043df6c6efbbd4f39fc45737841776592
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / Http / RequestHandler.php
1 <?php
2 declare(strict_types = 1);
3
4 namespace TYPO3\CMS\Frontend\Http;
5
6 /*
7 * This file is part of the TYPO3 CMS project.
8 *
9 * It is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License, either version 2
11 * of the License, or any later version.
12 *
13 * For the full copyright and license information, please read the
14 * LICENSE.txt file that was distributed with this source code.
15 *
16 * The TYPO3 project - inspiring people to share!
17 */
18
19 use Psr\Http\Message\ResponseInterface;
20 use Psr\Http\Message\ServerRequestInterface;
21 use Psr\Http\Server\RequestHandlerInterface as PsrRequestHandlerInterface;
22 use TYPO3\CMS\Core\Http\NullResponse;
23 use TYPO3\CMS\Core\Http\RequestHandlerInterface;
24 use TYPO3\CMS\Core\Http\Response;
25 use TYPO3\CMS\Core\TimeTracker\TimeTracker;
26 use TYPO3\CMS\Core\Utility\GeneralUtility;
27 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
28 use TYPO3\CMS\Frontend\Page\PageGenerator;
29
30 /**
31 * This is the main entry point of the TypoScript driven standard front-end
32 *
33 * Basically put, this is the script which all requests for TYPO3 delivered pages goes to in the
34 * frontend (the website). The script instantiates a $TSFE object, includes libraries and does a little logic here
35 * and there in order to instantiate the right classes to create the webpage.
36 * Previously, this was called index_ts.php and also included the logic for the lightweight "eID" concept,
37 * which is now handled in a separate middleware (EidHandler).
38 */
39 class RequestHandler implements RequestHandlerInterface, PsrRequestHandlerInterface
40 {
41 /**
42 * Instance of the timetracker
43 * @var TimeTracker
44 */
45 protected $timeTracker;
46
47 /**
48 * Handles a frontend request
49 *
50 * @param ServerRequestInterface $request
51 * @return ResponseInterface
52 */
53 public function handleRequest(ServerRequestInterface $request): ResponseInterface
54 {
55 return $this->handle($request);
56 }
57
58 /**
59 * Handles a frontend request, after finishing running middlewares
60 *
61 * @param ServerRequestInterface $request
62 * @return ResponseInterface|null
63 */
64 public function handle(ServerRequestInterface $request): ResponseInterface
65 {
66 // Fetch the initialized time tracker object
67 $this->timeTracker = GeneralUtility::makeInstance(TimeTracker::class);
68 /** @var TypoScriptFrontendController $controller */
69 $controller = $GLOBALS['TSFE'];
70
71 // Generate page
72 if ($controller->isGeneratePage()) {
73 $this->timeTracker->push('Page generation');
74 $controller->generatePage_preProcessing();
75 $controller->preparePageContentGeneration();
76 // Content generation
77 PageGenerator::renderContent();
78 $controller->setAbsRefPrefix();
79 $controller->generatePage_postProcessing();
80 $this->timeTracker->pull();
81 }
82 $controller->releaseLocks();
83
84 // Render non-cached page parts by replacing placeholders which are taken from cache or added during page generation
85 if ($controller->isINTincScript()) {
86 if (!$controller->isGeneratePage()) {
87 // When page was generated, this was already called. Avoid calling this twice.
88 $controller->preparePageContentGeneration();
89 }
90 $this->timeTracker->push('Non-cached objects');
91 $controller->INTincScript();
92 $this->timeTracker->pull();
93 }
94
95 // Create a Response object when sending content
96 $response = new Response();
97
98 // Output content
99 $isOutputting = $controller->isOutputting();
100 if ($isOutputting) {
101 $this->timeTracker->push('Print Content');
102 $controller->processOutput();
103 $this->timeTracker->pull();
104 }
105 // Store session data for fe_users
106 $controller->storeSessionData();
107
108 $redirectResponse = $controller->redirectToExternalUrl();
109 if ($redirectResponse instanceof ResponseInterface) {
110 return $redirectResponse;
111 }
112
113 // Statistics
114 $GLOBALS['TYPO3_MISC']['microtime_end'] = microtime(true);
115 if ($isOutputting && ($controller->config['config']['debug'] ?? !empty($GLOBALS['TYPO3_CONF_VARS']['FE']['debug']))) {
116 $response = $response->withHeader('X-TYPO3-Parsetime', $this->timeTracker->getParseTime() . 'ms');
117 }
118
119 // Preview info
120 $controller->previewInfo();
121 // Hook for end-of-frontend
122 $controller->hook_eofe();
123 // Finish timetracking
124 $this->timeTracker->pull();
125
126 if ($isOutputting) {
127 $response->getBody()->write($controller->content);
128 }
129
130 return $isOutputting ? $response : new NullResponse();
131 }
132
133 /**
134 * This request handler can handle any frontend request.
135 *
136 * @param ServerRequestInterface $request
137 * @return bool If the request is not an eID request, TRUE otherwise FALSE
138 */
139 public function canHandleRequest(ServerRequestInterface $request): bool
140 {
141 return true;
142 }
143
144 /**
145 * Returns the priority - how eager the handler is to actually handle the
146 * request.
147 *
148 * @return int The priority of the request handler.
149 */
150 public function getPriority(): int
151 {
152 return 50;
153 }
154 }