1<?php
2
3
4namespace ComboStrap;
5
6
7class Http
8{
9
10    public static function removeHeaderIfPresent(string $key)
11    {
12        foreach (headers_list() as $header) {
13            if (preg_match("/$key/i", $header)) {
14                header_remove($key);
15            }
16        }
17
18    }
19
20    /**
21     * @throws ExceptionNotFound
22     */
23    public static function getFirstHeader(string $name, array $headers = null): string
24    {
25
26        $result = self::getHeadersForName($name, $headers);
27
28        if (count($result) == 0) {
29            throw new ExceptionNotFound("No header was found with the header name $name");
30        }
31
32        return $result[0];
33
34
35    }
36
37    private static function getHeaders(): array
38    {
39        return (function_exists('xdebug_get_headers') ? xdebug_get_headers() : headers_list());
40    }
41
42    /**
43     * Set the HTTP status
44     * Dokuwiki test does not {@link \TestResponse::getStatusCode()} capture the status with all php function such
45     * as {@link http_response_code},
46     *
47     * @param int $int
48     */
49    public static function setStatus(int $int)
50    {
51        /**
52         * {@link http_status} function
53         * that creates
54         * header('HTTP/1.1 301 Moved Permanently');
55         * header('HTTP/1.0 304 Not Modified');
56         * header('HTTP/1.1 404 Not Found');
57         *
58         * not {@link http_response_code}
59         */
60        http_status($int);
61
62    }
63
64    public static function getStatus()
65    {
66        /**
67         * See also {@link Http::getFirstHeader()}
68         * if this does not work
69         */
70        return http_response_code();
71    }
72
73    public static function setMime(string $mime)
74    {
75        $contentTypeHeader = HttpResponse::HEADER_CONTENT_TYPE;
76        header("$contentTypeHeader: $mime");
77    }
78
79
80    public static function getHeadersForName(string $name, ?array $headers): array
81    {
82        if ($headers === null) {
83            $headers = self::getHeaders();
84        }
85
86        $result = array();
87        $headerNameNormalized = trim(strtolower($name));
88        foreach ($headers as $header) {
89            $loc = strpos($header, ":");
90            if ($loc === false) {
91                continue;
92            }
93            $actualHeaderName = substr($header, 0, $loc);
94            $actualHeaderNameNormalized = trim(strtolower($actualHeaderName));
95            if ($actualHeaderNameNormalized === $headerNameNormalized) {
96                $result[] = $header;
97            }
98        }
99        return $result;
100    }
101
102    /**
103     * @throws ExceptionNotExists
104     */
105    public static function extractHeaderValue(string $header): string
106    {
107        $positionDoublePointSeparator = strpos($header, ':');
108        if ($positionDoublePointSeparator === false) {
109            throw new ExceptionNotExists("No value found");
110        }
111        return trim(substr($header, $positionDoublePointSeparator + 1));
112    }
113
114    /**
115     * PHP is blocking and fsockopen also.
116     * Don't use it in a page rendering flow
117     * https://segment.com/blog/how-to-make-async-requests-in-php/
118     * @param $url
119     */
120    function sendAsyncRequest($url)
121    {
122        $parts = parse_url($url);
123        $fp = fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80, $errno, $errstr, 30);
124        $out = "GET " . $parts['path'] . "?" . $parts['query'] . " HTTP/1.1\r\n";
125        $out .= "Host: " . $parts['host'] . "\r\n";
126        $out .= "Content-Length: 0" . "\r\n";
127        $out .= "Connection: Close\r\n\r\n";
128
129        fwrite($fp, $out);
130        fclose($fp);
131    }
132
133
134}
135