|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* HttpStatusModel.php |
|
4
|
|
|
* @author Marc-André Appel <[email protected]> |
|
5
|
|
|
* @copyright 2018 Hybride Conseil |
|
6
|
|
|
* @license http://opensource.org/licenses/MIT MIT |
|
7
|
|
|
* @link https://www.hybride-conseil.fr |
|
8
|
|
|
* @created 19/06/2018 |
|
9
|
|
|
*/ |
|
10
|
|
|
|
|
11
|
|
|
declare(strict_types=1); |
|
12
|
|
|
|
|
13
|
|
|
namespace MarcAndreAppel\HttpStatus; |
|
14
|
|
|
|
|
15
|
|
|
use MarcAndreAppel\HttpStatus\Exceptions\HeaderSentException; |
|
16
|
|
|
|
|
17
|
|
|
class HttpStatus |
|
18
|
|
|
{ |
|
19
|
|
|
public $code; |
|
20
|
|
|
public $title; |
|
21
|
|
|
public $message; |
|
22
|
|
|
|
|
23
|
|
|
private $version = 1.0; |
|
24
|
|
|
|
|
25
|
|
|
private static $titles = array( |
|
26
|
|
|
100 => "Continue", |
|
27
|
|
|
101 => "Switching Protocols", |
|
28
|
|
|
102 => "Processing", |
|
29
|
|
|
103 => "Early Hints", |
|
30
|
|
|
|
|
31
|
|
|
200 => "OK", |
|
32
|
|
|
201 => "Created", |
|
33
|
|
|
202 => "Accepted", |
|
34
|
|
|
203 => "Non-Authoritative Information", |
|
35
|
|
|
204 => "No Content", |
|
36
|
|
|
205 => "Reset Content", |
|
37
|
|
|
206 => "Partial Content", |
|
38
|
|
|
207 => "Multi-Status", |
|
39
|
|
|
208 => "Already Reported", |
|
40
|
|
|
226 => "IM Used", |
|
41
|
|
|
|
|
42
|
|
|
300 => "Multiple Choices", |
|
43
|
|
|
301 => "Moved Permanently", |
|
44
|
|
|
302 => "Found", |
|
45
|
|
|
303 => "See Other", |
|
46
|
|
|
304 => "Not Modified", |
|
47
|
|
|
305 => "Use Proxy", |
|
48
|
|
|
307 => "Temporary Redirect", |
|
49
|
|
|
308 => "Permanent Redirect", |
|
50
|
|
|
|
|
51
|
|
|
400 => "Bad Request", |
|
52
|
|
|
401 => "Unauthorized", |
|
53
|
|
|
402 => "Payment Required", |
|
54
|
|
|
403 => "Forbidden", |
|
55
|
|
|
404 => "Not Found", |
|
56
|
|
|
405 => "Method Not Allowed", |
|
57
|
|
|
406 => "Not Acceptable", |
|
58
|
|
|
407 => "Proxy Authentication Required", |
|
59
|
|
|
408 => "Request Timeout", |
|
60
|
|
|
409 => "Conflict", |
|
61
|
|
|
410 => "Gone", |
|
62
|
|
|
411 => "Length Required", |
|
63
|
|
|
412 => "Precondition Failed", |
|
64
|
|
|
413 => "Payload Too Large", |
|
65
|
|
|
414 => "URI Too Long", |
|
66
|
|
|
415 => "Unsupported Media Type", |
|
67
|
|
|
416 => "Range Not Satisfiable", |
|
68
|
|
|
417 => "Expectation Failed", |
|
69
|
|
|
418 => "I\'m a teapot", |
|
70
|
|
|
421 => "Misdirected Request", |
|
71
|
|
|
422 => "Unprocessable Entity", |
|
72
|
|
|
423 => "Locked", |
|
73
|
|
|
424 => "Failed Dependency", |
|
74
|
|
|
425 => "Reserved for WebDAV advanced collections expired proposal", |
|
75
|
|
|
426 => "Upgrade Required", |
|
76
|
|
|
428 => "Precondition Required", |
|
77
|
|
|
429 => "Too Many Requests", |
|
78
|
|
|
431 => "Request Header Fields Too Large", |
|
79
|
|
|
451 => "Unavailable For Legal Reasons", |
|
80
|
|
|
|
|
81
|
|
|
500 => "Internal Server Error", |
|
82
|
|
|
501 => "Not Implemented", |
|
83
|
|
|
502 => "Bad Gateway", |
|
84
|
|
|
503 => "Service Unavailable", |
|
85
|
|
|
504 => "Gateway Timeout", |
|
86
|
|
|
505 => "HTTP Version Not Supported", |
|
87
|
|
|
506 => "Variant Also Negotiates", |
|
88
|
|
|
507 => "Insufficient Storage", |
|
89
|
|
|
508 => "Loop Detected", |
|
90
|
|
|
510 => "Not Extended", |
|
91
|
|
|
511 => "Network Authentication Required", |
|
92
|
|
|
); |
|
93
|
|
|
|
|
94
|
|
|
private static $messages = array( |
|
95
|
|
|
200 => "Standard response for successful HTTP requests.", |
|
96
|
|
|
201 => "The request has been fulfilled, resulting in the creation of a new resource.", |
|
97
|
|
|
202 => "The request has been accepted for processing, but the processing has not been completed.", |
|
98
|
|
|
203 => "The server is a transforming proxy (e.g. a Web accelerator) that received a 200 OK from its origin, but is returning a modified version of the origin\"s response.", |
|
99
|
|
|
204 => "The server successfully processed the request and is not returning any content.", |
|
100
|
|
|
205 => "The server successfully processed the request, but is not returning any content.", |
|
101
|
|
|
206 => "The server is delivering only part of the resource (byte serving) due to a range header sent by the client.", |
|
102
|
|
|
207 => "The message body that follows is an XML message and can contain a number of separate response codes, depending on how many sub-requests were made.", |
|
103
|
|
|
208 => "The members of a DAV binding have already been enumerated in a previous reply to this request, and are not being included again.", |
|
104
|
|
|
226 => "The server has fulfilled a request for the resource, and the response is a representation of the result of one or more instance-manipulations applied to the current instance.", |
|
105
|
|
|
|
|
106
|
|
|
300 => "Indicates multiple options for the resource from which the client may choose.", |
|
107
|
|
|
301 => "This and all future requests should be directed to the given URI.", |
|
108
|
|
|
302 => "This is an example of industry practice contradicting the standard.", |
|
109
|
|
|
303 => "The response to the request can be found under another URI using a GET method.", |
|
110
|
|
|
304 => "Indicates that the resource has not been modified since the version specified by the request headers If-Modified-Since or If-None-Match.", |
|
111
|
|
|
305 => "The requested resource is available only through a proxy, the address for which is provided in the response.", |
|
112
|
|
|
306 => "No longer used.", |
|
113
|
|
|
307 => "In this case, the request should be repeated with another URI; however, future requests should still use the original URI.", |
|
114
|
|
|
308 => "The request and all future requests should be repeated using another URI.", |
|
115
|
|
|
|
|
116
|
|
|
400 => "The request cannot be fulfilled due to bad syntax.", |
|
117
|
|
|
401 => "Authentication is required and has failed or has not yet been provided.", |
|
118
|
|
|
402 => "Reserved for future use.", |
|
119
|
|
|
403 => "The request was a valid request, but the server is refusing to respond to it.", |
|
120
|
|
|
404 => "The requested resource could not be found but may be available again in the future.", |
|
121
|
|
|
405 => "A request was made of a resource using a request method not supported by that resource.", |
|
122
|
|
|
406 => "The requested resource is only capable of generating content not acceptable.", |
|
123
|
|
|
407 => "Proxy authentication is required to access the requested resource.", |
|
124
|
|
|
408 => "The server did not receive a complete request message in time.", |
|
125
|
|
|
409 => "The request could not be processed because of conflict in the request.", |
|
126
|
|
|
410 => "The requested resource is no longer available and will not be available again.", |
|
127
|
|
|
411 => "The request did not specify the length of its content, which is required by the resource.", |
|
128
|
|
|
412 => "The server does not meet one of the preconditions that the requester put on the request.", |
|
129
|
|
|
413 => "The server cannot process the request because the request payload is too large.", |
|
130
|
|
|
414 => "The request-target is longer than the server is willing to interpret.", |
|
131
|
|
|
415 => "The request entity has a media type which the server or resource does not support.", |
|
132
|
|
|
416 => "The client has asked for a portion of the file, but the server cannot supply that portion.", |
|
133
|
|
|
417 => "The expectation given could not be met by at least one of the inbound servers.", |
|
134
|
|
|
418 => "I\'m a teapot", |
|
135
|
|
|
421 => "The request was directed at a server that is not able to produce a response.", |
|
136
|
|
|
422 => "The request was well-formed but was unable to be followed due to semantic errors.", |
|
137
|
|
|
423 => "The resource that is being accessed is locked.", |
|
138
|
|
|
424 => "The request failed due to failure of a previous request.", |
|
139
|
|
|
426 => "The server cannot process the request using the current protocol.", |
|
140
|
|
|
428 => "The origin server requires the request to be conditional.", |
|
141
|
|
|
429 => "The user has sent too many requests in a given amount of time.", |
|
142
|
|
|
431 => "The server is unwilling to process the request because either an individual header field, or all the header fields collectively, are too large.", |
|
143
|
|
|
451 => "Resource access is denied for legal reasons.", |
|
144
|
|
|
|
|
145
|
|
|
500 => "An error has occurred and this resource cannot be displayed.", |
|
146
|
|
|
501 => "The server either does not recognize the request method, or it lacks the ability to fulfil the request.", |
|
147
|
|
|
502 => "The server was acting as a gateway or proxy and received an invalid response from the upstream server.", |
|
148
|
|
|
503 => "The server is currently unavailable. It may be overloaded or down for maintenance.", |
|
149
|
|
|
504 => "The server was acting as a gateway or proxy and did not receive a timely response from the upstream server.", |
|
150
|
|
|
505 => "The server does not support the HTTP protocol version used in the request.", |
|
151
|
|
|
506 => "Transparent content negotiation for the request, results in a circular reference.", |
|
152
|
|
|
507 => "The method could not be performed on the resource because the server is unable to store the representation needed to successfully complete the request. There is insufficient free space left in your storage allocation.", |
|
153
|
|
|
508 => "The server detected an infinite loop while processing the request.", |
|
154
|
|
|
510 => "Further extensions to the request are required for the server to fulfill it.A mandatory extension policy in the request is not accepted by the server for this resource.", |
|
155
|
|
|
511 => "The client needs to authenticate to gain network access.", |
|
156
|
|
|
); |
|
157
|
|
|
|
|
158
|
|
|
public function __construct(int $code = null) |
|
159
|
|
|
{ |
|
160
|
|
|
if (is_null($code)) { |
|
161
|
|
|
throw new \InvalidArgumentException("Cannot be null nor empty"); |
|
162
|
|
|
} |
|
163
|
|
|
if ( ! key_exists($code, self::$titles) || ! is_int($code)) { |
|
164
|
|
|
throw new \OutOfBoundsException("Not a valid integer or not a valid HTTP status code"); |
|
165
|
|
|
} |
|
166
|
|
|
|
|
167
|
|
|
$this->code = $code; |
|
168
|
|
|
$this->title = self::$titles[$code]; |
|
169
|
|
|
$this->message = self::$messages[$code] ?? null; |
|
170
|
|
|
|
|
171
|
|
|
$this->setProtocol(); |
|
172
|
|
|
|
|
173
|
|
|
return $this; |
|
174
|
|
|
} |
|
175
|
|
|
|
|
176
|
|
|
|
|
177
|
|
|
/** |
|
178
|
|
|
* @throws \MarcAndreAppel\HttpStatus\Exceptions\HeaderSentException |
|
179
|
|
|
*/ |
|
180
|
|
|
public function header() |
|
181
|
|
|
{ |
|
182
|
|
|
if (headers_sent()) { |
|
183
|
|
|
throw new HeaderSentException(); |
|
184
|
|
|
} else { |
|
185
|
|
|
$header = sprintf("HTTP/%s %s %s", $this->version, $this->code, $this->title); |
|
186
|
|
|
header($header, true, $this->code); |
|
187
|
|
|
} |
|
188
|
|
|
} |
|
189
|
|
|
|
|
190
|
|
|
private function setProtocol() |
|
191
|
|
|
{ |
|
192
|
|
|
if ("HTTP/1.0" != $_SERVER['SERVER_PROTOCOL']) { |
|
193
|
|
|
$this->version = 1.1; |
|
194
|
|
|
} |
|
195
|
|
|
return $this; |
|
196
|
|
|
} |
|
197
|
|
|
} |