• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eliashaeussler / typo3-warming / 15664888806

15 Jun 2025 03:51PM UTC coverage: 91.643% (-0.1%) from 91.788%
15664888806

push

github

web-flow
Merge pull request #889 from eliashaeussler/fix/sub-request

13 of 15 new or added lines in 1 file covered. (86.67%)

1634 of 1783 relevant lines covered (91.64%)

12.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.59
/Classes/Http/Client/Handler/SubRequestHandler.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of the TYPO3 CMS extension "warming".
7
 *
8
 * Copyright (C) 2021-2025 Elias Häußler <elias@haeussler.dev>
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation, either version 2 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22
 */
23

24
namespace EliasHaeussler\Typo3Warming\Http\Client\Handler;
25

26
use EliasHaeussler\Typo3Warming\Http;
27
use GuzzleHttp\Exception;
28
use GuzzleHttp\Promise;
29
use GuzzleHttp\Utils;
30
use Psr\Http\Message;
31
use Symfony\Component\DependencyInjection;
32
use TYPO3\CMS\Core;
33
use TYPO3\CMS\Frontend;
34

35
/**
36
 * SubRequestHandler
37
 *
38
 * @author Elias Häußler <elias@haeussler.dev>
39
 * @license GPL-2.0-or-later
40
 */
41
#[DependencyInjection\Attribute\Autoconfigure(public: true)]
42
final class SubRequestHandler
43
{
44
    /**
45
     * @var callable(Message\RequestInterface, array<string, mixed>): Promise\PromiseInterface
46
     */
47
    private $fallbackHandler;
48

49
    public function __construct(
14✔
50
        private readonly Frontend\Http\Application $application,
51
        private readonly Http\Message\UrlMetadataFactory $urlMetadataFactory,
52
        private readonly Core\Routing\SiteMatcher $siteMatcher,
53
    ) {
54
        $this->fallbackHandler = Utils::chooseHandler();
14✔
55
    }
56

57
    /**
58
     * @param array<string, mixed> $options
59
     */
60
    public function __invoke(Message\RequestInterface $request, array $options): Promise\PromiseInterface
5✔
61
    {
62
        $subRequest = new Core\Http\ServerRequest(
5✔
63
            $request->getUri(),
5✔
64
            $request->getMethod(),
5✔
65
            $request->getBody(),
5✔
66
            $request->getHeaders(),
5✔
67
        );
5✔
68

69
        if (!$this->isSupportedRequest($subRequest)) {
5✔
70
            return ($this->fallbackHandler)($request, $options);
1✔
71
        }
72

73
        $globalsBackup = $GLOBALS;
4✔
74

75
        try {
76
            return $this->sendSubRequest($request, $subRequest);
4✔
77
        } finally {
78
            foreach ($globalsBackup as $key => $value) {
4✔
79
                $GLOBALS[$key] = $value;
4✔
80
            }
81
        }
82
    }
83

84
    private function sendSubRequest(
4✔
85
        Message\RequestInterface $request,
86
        Message\ServerRequestInterface $subRequest,
87
    ): Promise\PromiseInterface {
88
        $response = null;
4✔
89

90
        try {
91
            return Promise\Create::promiseFor(
4✔
92
                $this->application->handle($subRequest),
4✔
93
            );
4✔
94
        } catch (Core\Http\ImmediateResponseException $exception) {
3✔
95
            $response = $exception->getResponse();
1✔
96
        } catch (Core\Error\Http\StatusException $exception) {
2✔
97
            $response = new Core\Http\Response(statusCode: 500);
1✔
98
            $metadata = $this->urlMetadataFactory->createFromResponseHeaders($exception->getStatusHeaders());
1✔
99

100
            if ($metadata !== null) {
1✔
101
                $response = $this->urlMetadataFactory->enrichResponse($response, $metadata);
1✔
102
            }
103
        } catch (\Exception $exception) {
1✔
104
        }
105

106
        return Promise\Create::rejectionFor(
3✔
107
            new Exception\RequestException($exception->getMessage(), $request, $response),
3✔
108
        );
3✔
109
    }
110

111
    private function isSupportedRequest(Message\ServerRequestInterface $subRequest): bool
5✔
112
    {
113
        try {
114
            $routeResult = $this->siteMatcher->matchRequest($subRequest);
5✔
NEW
115
        } catch (\Exception) {
×
NEW
116
            return false;
×
117
        }
118

119
        return $routeResult instanceof Core\Routing\SiteRouteResult
5✔
120
            && $routeResult->getSite() instanceof Core\Site\Entity\Site;
5✔
121
    }
122
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc