Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
RequestServiceProvider
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
2 / 2
13
100.00% covered (success)
100.00%
1 / 1
 register
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
5
 createRequestWithoutPrefix
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
7
 setTrustedProxies
n/a
0 / 0
n/a
0 / 0
1
1<?php
2
3declare(strict_types=1);
4
5namespace Engelsystem\Http;
6
7use Engelsystem\Config\Config;
8use Engelsystem\Container\ServiceProvider;
9use Illuminate\Support\Str;
10use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
11
12class RequestServiceProvider extends ServiceProvider
13{
14    protected array $appUrl;
15
16    public function register(): void
17    {
18        /** @var Config $config */
19        $config = $this->app->get('config');
20        $trustedProxies = $config->get('trusted_proxies', []);
21        $this->appUrl = parse_url($config->get('url') ?: '');
22
23        if (!is_array($trustedProxies)) {
24            $trustedProxies = empty($trustedProxies) ? [] : explode(',', preg_replace('~\s+~', '', $trustedProxies));
25        }
26
27        if (!empty($this->appUrl['path'])) {
28            Request::setFactory($this->createRequestWithoutPrefix(...));
29        }
30
31        /** @var Request $request */
32        $request = $this->app->call([Request::class, 'createFromGlobals']);
33        $this->setTrustedProxies($request, $trustedProxies);
34
35        $this->app->instance(Request::class, $request);
36        $this->app->instance(SymfonyRequest::class, $request);
37        $this->app->instance('request', $request);
38    }
39
40    /**
41     * @param array $query GET parameters
42     * @param array $request POST parameters
43     * @param array $attributes Additional data
44     * @param array $cookies Cookies
45     * @param array $files Uploaded files
46     * @param array $server Server env
47     * @param mixed $content Request content
48     */
49    public function createRequestWithoutPrefix(
50        array $query = [],
51        array $request = [],
52        array $attributes = [],
53        array $cookies = [],
54        array $files = [],
55        array $server = [],
56        mixed $content = null
57    ): Request {
58        if (
59            !empty($this->appUrl['path'])
60            && !empty($server['REQUEST_URI'])
61            && Str::startsWith($server['REQUEST_URI'], $this->appUrl['path'])
62        ) {
63            $requestUri = Str::substr(
64                $server['REQUEST_URI'],
65                Str::length(rtrim($this->appUrl['path'], '/'))
66            );
67
68            // Reset paths which only contain the app path
69            if ($requestUri && !Str::startsWith($requestUri, '/')) {
70                $requestUri = $server['REQUEST_URI'];
71            }
72
73            $server['REQUEST_URI'] = $requestUri ?: '/';
74        }
75
76        return new Request($query, $request, $attributes, $cookies, $files, $server, $content);
77    }
78
79    /**
80     * Set the trusted Proxies
81     *
82     * Required for unit tests (static methods can't be mocked)
83     * @codeCoverageIgnore
84     */
85    protected function setTrustedProxies(
86        Request $request,
87        array $proxies,
88        int $trustedHeadersSet = Request::HEADER_FORWARDED | Request::HEADER_X_FORWARDED_TRAEFIK
89    ): void {
90        $request->setTrustedProxies($proxies, $trustedHeadersSet);
91    }
92}