[TASK] Directly wire Application and RequestHandler
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Http / AbstractApplication.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Core\Http;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 use Psr\Http\Message\ResponseInterface;
19 use Psr\Http\Message\ServerRequestInterface;
20 use Psr\Http\Server\RequestHandlerInterface;
21 use TYPO3\CMS\Core\Core\ApplicationInterface;
22 use TYPO3\CMS\Core\Core\Bootstrap;
23 use TYPO3\CMS\Core\Utility\GeneralUtility;
24
25 /**
26 * @internal
27 */
28 class AbstractApplication implements ApplicationInterface
29 {
30 /**
31 * @var string
32 */
33 protected $requestHandler = '';
34
35 /**
36 * @var string
37 */
38 protected $middlewareStack = '';
39
40 /**
41 * @param RequestHandlerInterface $requestHandler
42 * @return MiddlewareDispatcher
43 */
44 protected function createMiddlewareDispatcher(RequestHandlerInterface $requestHandler): MiddlewareDispatcher
45 {
46 $resolver = new MiddlewareStackResolver(
47 GeneralUtility::makeInstance(\TYPO3\CMS\Core\Package\PackageManager::class),
48 GeneralUtility::makeInstance(\TYPO3\CMS\Core\Service\DependencyOrderingService::class),
49 GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('cache_core')
50 );
51 $middlewares = $resolver->resolve($this->middlewareStack);
52
53 return new MiddlewareDispatcher($requestHandler, $middlewares);
54 }
55
56 /**
57 * Outputs content
58 *
59 * @param ResponseInterface $response
60 */
61 protected function sendResponse(ResponseInterface $response)
62 {
63 if ($response instanceof \TYPO3\CMS\Core\Http\NullResponse) {
64 return;
65 }
66
67 if (!headers_sent()) {
68 // If the response code was not changed by legacy code (still is 200)
69 // then allow the PSR-7 response object to explicitly set it.
70 // Otherwise let legacy code take precedence.
71 // This code path can be deprecated once we expose the response object to third party code
72 if (http_response_code() === 200) {
73 header('HTTP/' . $response->getProtocolVersion() . ' ' . $response->getStatusCode() . ' ' . $response->getReasonPhrase());
74 }
75
76 foreach ($response->getHeaders() as $name => $values) {
77 header($name . ': ' . implode(', ', $values));
78 }
79 }
80 echo $response->getBody()->__toString();
81 }
82
83 /**
84 * @param ServerRequestInterface $request
85 * @return ResponseInterface
86 */
87 protected function handle(ServerRequestInterface $request): ResponseInterface
88 {
89 $requestHandler = GeneralUtility::makeInstance($this->requestHandler, Bootstrap::getInstance());
90 $dispatcher = $this->createMiddlewareDispatcher($requestHandler);
91
92 return $dispatcher->handle($request);
93 }
94
95 /**
96 * Set up the application and shut it down afterwards
97 *
98 * @param callable $execute
99 */
100 public function run(callable $execute = null)
101 {
102 $response = $this->handle(\TYPO3\CMS\Core\Http\ServerRequestFactory::fromGlobals());
103
104 if ($execute !== null) {
105 call_user_func($execute);
106 }
107
108 $this->sendResponse($response);
109 }
110 }