Issues (21)

src/Domain/Header/AbstractHeaderProvider.php (1 issue)

Labels
Severity
1
<?php declare(strict_types=1);
2
3
/**
4
 * @license  http://opensource.org/licenses/mit-license.php MIT
5
 * @link     https://github.com/nicoSWD
6
 * @author   Nicolas Oelgart <[email protected]>
7
 */
8
namespace nicoSWD\SecHeaderCheck\Domain\Header;
9
10
use nicoSWD\SecHeaderCheck\Domain\Header\Exception\TooManyRedirectsException;
11
use nicoSWD\SecHeaderCheck\Domain\URL\URL;
12
13
abstract class AbstractHeaderProvider implements HeaderProviderInterface
14
{
15
    /** @var int */
16
    private $maxRedirects;
17
    /** @var int */
18
    protected $connectionTimeout;
19
20
    public function __construct(int $maxRedirects, int $connectionTimeout)
21
    {
22
        $this->maxRedirects = $maxRedirects;
23
        $this->connectionTimeout = $connectionTimeout;
24
    }
25
26
    abstract public function getRawHeaders(URL $url): string;
27
28 2
    public function getHeadersFromUrl(URL $url, bool $followRedirects = true): HttpHeaderBag
29
    {
30 2
        $headers = $this->getHeadersFromString($this->getRawHeaders($url));
31
32 2
        if ($followRedirects) {
33 2
            $headers = $this->getRawHeadersFromRedirectingUrl($url, $headers);
34
        }
35
36 2
        return $headers;
37
    }
38
39 2
    public function getHeadersFromString(string $headers): HttpHeaderBag
40
    {
41 2
        $headersLines = preg_split('~\r?\n~', $headers, -1, PREG_SPLIT_NO_EMPTY);
42 2
        $parsedHeaders = [];
43
44 2
        $firstLine = array_shift($headersLines);
0 ignored issues
show
It seems like $headersLines can also be of type false; however, parameter $array of array_shift() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

44
        $firstLine = array_shift(/** @scrutinizer ignore-type */ $headersLines);
Loading history...
45
46 2
        [$headerName, $headerValue] = explode(' ', $firstLine, 2);
47 2
        $parsedHeaders[$headerName][] = $headerValue;
48
49 2
        foreach ($headersLines as $line) {
50 2
            [$headerName, $headerValue] = $this->getNameAndValue($line);
51 2
            $parsedHeaders[$headerName][] = $headerValue;
52
        }
53
54 2
        return $this->headerArrayToBag($parsedHeaders);
55
    }
56
57 2
    private function headerArrayToBag(array $headers): HttpHeaderBag
58
    {
59 2
        $headerBag = new HttpHeaderBag();
60
61 2
        foreach ($headers as $headerName => $values) {
62 2
            foreach ($values as $value) {
63 2
                $headerBag->add($this->createHeader($headerName, $value));
64
            }
65
        }
66
67 2
        return $headerBag;
68
    }
69
70 2
    private function getRawHeadersFromRedirectingUrl(URL $url, HttpHeaderBag $headers): HttpHeaderBag
71
    {
72 2
        $numRedirects = 0;
73
74 2
        while ($headers->has('location')) {
75
            if (++$numRedirects > $this->maxRedirects) {
76
                throw new TooManyRedirectsException();
77
            }
78
79
            $headers = $this->getHeadersFromString(
80
                $this->getRawHeaders($url->redirectTo($headers->getFirst('location')))
81
            );
82
        }
83
84 2
        return $headers;
85
    }
86
87 2
    protected function getNameAndValue(string $line): array
88
    {
89 2
        $parts = explode(':', $line, 2);
90 2
        $headerName = trim(strtolower($parts[0]));
91 2
        $headerValue = trim($parts[1] ?? '');
92
93 2
        return [$headerName, $headerValue];
94
    }
95
96 2
    private function createHeader(string $headerName, string $value): HttpHeader
97
    {
98 2
        return new HttpHeader(strtolower(trim($headerName)), $value);
99
    }
100
}
101