Passed
Push — master ( f4aea8...91cb90 )
by Alexander
01:38
created

src/util/Http.php (1 issue)

1
<?php
2
3
namespace alkemann\h2l\util;
4
5
/**
6
 * Class Http
7
 *
8
 * Holds HTTP Spec constants,
9
 *
10
 * @package alkemann\h2l\util
11
 */
12
class Http
13
{
14
    public const TRACE = 'TRACE';
15
    public const HEAD = 'HEAD';
16
    public const POST = 'POST';
17
    public const CONNECT = 'CONNECT';
18
    public const OPTIONS = 'OPTIONS';
19
    public const PUT = 'PUT';
20
    public const PATCH = 'PATCH';
21
    public const DELETE = 'DELETE';
22
    public const GET = 'GET';
23
24
    public const CONTENT_HTML = 'text/html';
25
    public const CONTENT_TEXT_XML = 'text/xml';
26
    public const CONTENT_XML = 'application/xml';
27
    public const CONTENT_TEXT = 'text/plain';
28
    public const CONTENT_FORM = 'application/x-www-form-urlencoded';
29
    public const CONTENT_JSON = 'application/json';
30
31
    public const CODE_CONTINUE = 100;
32
    public const CODE_SWITCHING_PROTOCOLS = 101;
33
34
    public const CODE_OK = 200;
35
    public const CODE_CREATED = 201;
36
    public const CODE_ACCEPTED = 202;
37
    public const CODE_NON_AUTHORITATIVE_INFORMATION = 203;
38
    public const CODE_NO_CONTENT = 204;
39
    public const CODE_RESET_CONTENT = 205;
40
    public const CODE_PARTIAL_CONTENT = 206;
41
42
    public const CODE_MULTIPLE_CHOICES = 300;
43
    public const CODE_MOVED_PERMANENTLY = 301;
44
    public const CODE_FOUND = 302;
45
    public const CODE_SEE_OTHER = 303;
46
    public const CODE_NOT_MODIFIED = 304;
47
    public const CODE_USE_PROXY = 305;
48
    public const CODE_TEMPORARY_REDIRECT = 307;
49
50
    public const CODE_BAD_REQUEST = 400;
51
    public const CODE_UNAUTHORIZED = 401;
52
    public const CODE_PAYMENT_REQUIRED = 402;
53
    public const CODE_FORBIDDEN = 403;
54
    public const CODE_NOT_FOUND = 404;
55
    public const CODE_METHOD_NOT_ALLOWED = 405;
56
    public const CODE_NOT_ACCEPTABLE = 406;
57
    public const CODE_PROXY_AUTHENTICATION_REQUIRED = 407;
58
    public const CODE_REQUEST_TIMEOUT = 408;
59
    public const CODE_CONFLICT = 409;
60
    public const CODE_GONE = 410;
61
    public const CODE_LENGTH_REQUIRED = 411;
62
    public const CODE_PRECONDITION_FAILED = 412;
63
    public const CODE_REQUEST_ENTITY_TOO_LARGE = 413;
64
    public const CODE_REQUEST_URI_TOO_LONG = 414;
65
    public const CODE_UNSUPPORTED_MEDIA_TYPE = 415;
66
    public const CODE_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
67
    public const CODE_EXPECTATION_FAILED = 417;
68
69
    public const CODE_INTERNAL_SERVER_ERROR = 500;
70
    public const CODE_NOT_IMPLEMENTED = 501;
71
    public const CODE_BAD_GATEWAY = 502;
72
    public const CODE_SERVICE_UNAVAILABLE = 503;
73
    public const CODE_GATEWAY_TIMEOUT = 504;
74
    public const CODE_HTTP_VERSION_NOT_SUPPORTED = 505;
75
76
    /**
77
     * @var array<string, string>
78
     */
79
    protected static $contentTypeToFileEnding = [
80
        'text/html' => 'html',
81
        'application/json' => 'json',
82
        'application/xml' => 'xml',
83
        'text/xml' => 'xml',
84
        'text/plain' => 'txt',
85
    ];
86
87
    /**
88
     * @var array<int, string>
89
     */
90
    private static $code_to_message = [
91
        // Informational 1xx
92
        100 => 'Continue',
93
        101 => 'Switching Protocols',
94
        // Successful 2xx
95
        200 => 'OK',
96
        201 => 'Created',
97
        202 => 'Accepted',
98
        203 => 'Non-Authoritative Information',
99
        204 => 'No Content',
100
        205 => 'Reset Content',
101
        206 => 'Partial Content',
102
        // Redirection 3xx
103
        300 => 'Multiple Choices',
104
        301 => 'Moved Permanently',
105
        302 => 'Found',
106
        303 => 'See Other',
107
        304 => 'Not Modified',
108
        305 => 'Use Proxy',
109
        307 => 'Temporary Redirect',
110
        // Client Error 4xx
111
        400 => 'Bad Request',
112
        401 => 'Unauthorized',
113
        402 => 'Payment Required',
114
        403 => 'Forbidden',
115
        404 => 'Not Found',
116
        405 => 'Method Not Allowed',
117
        406 => 'Not Acceptable',
118
        407 => 'Proxy Authentication Required',
119
        408 => 'Request Timeout',
120
        409 => 'Conflict',
121
        410 => 'Gone',
122
        411 => 'Length Required',
123
        412 => 'Precondition Failed',
124
        413 => 'Request Entity Too Large',
125
        414 => 'Request-URI Too Long',
126
        415 => 'Unsupported Media Type',
127
        416 => 'Requested Range Not Satisfiable',
128
        417 => 'Expectation Failed',
129
        // Server Error 5xx
130
        500 => 'Internal Server Error',
131
        501 => 'Not Implemented',
132
        502 => 'Bad Gateway',
133
        503 => 'Service Unavailable',
134
        504 => 'Gateway Timeout',
135
        505 => 'HTTP Version Not Supported',
136
    ];
137
138
    /**
139
     * Convert a content type, i.e. "appliction/json", to a file ending, i.e. json"
140
     *
141
     * @param string $type
142
     * @return string
143
     */
144
    public static function fileEndingFromType(string $type): string
145
    {
146
        foreach (self::$contentTypeToFileEnding as $type_key => $ending) {
147
            if ($type === $type_key) {
148
                return $ending;
149
            }
150
        }
151
        return 'html';
152
    }
153
154
    /**
155
     * Convert a file ending, i.e. ".json", into a content type, i.e. "appliction/json"
156
     *
157
     * @param string $ending
158
     * @return string
159
     */
160
    public static function contentTypeFromFileEnding(string $ending): string
161
    {
162
        $type = array_search($ending, static::$contentTypeToFileEnding);
163
        return $type == false ? 'text/html' : $type;
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $type of type false|integer|string against false; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
164
    }
165
166
    /**
167
     * Convert and return the string "name" of a HTTP response code, or "Unknown"
168
     *
169
     * @param int $code
170
     * @return string
171
     */
172
    public static function httpCodeToMessage(int $code): string
173
    {
174
        return self::$code_to_message[$code] ?? "Unknown";
175
    }
176
177
    /**
178
     * Returns the request headers of a PHP Server array
179
     *
180
     * @param array $server_array
181
     * @return array
182
     */
183
    public static function getRequestHeadersFromServerArray(array $server_array): array
184
    {
185
        $out = [];
186
        foreach ($server_array as $name => $value) {
187
            if (substr($name, 0, 5) == "HTTP_") {
188
                $name = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($name, 5)))));
189
                $out[$name] = $value;
190
            }
191
        }
192
        if (array_key_exists("CONTENT_TYPE", $server_array)) {
193
            $out["Content-Type"] = $server_array['CONTENT_TYPE'];
194
        }
195
        if (array_key_exists("CONTENT_LENGTH", $server_array)) {
196
            $out["Content-Length"] = $server_array['CONTENT_LENGTH'];
197
        }
198
        return $out;
199
    }
200
}
201