Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
100.00% |
15 / 15 |
|
100.00% |
9 / 9 |
CRAP | |
100.00% |
1 / 1 |
| StatusCode | |
100.00% |
15 / 15 |
|
100.00% |
9 / 9 |
15 | |
100.00% |
1 / 1 |
| getCode | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getReasonPhrase | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getCategory | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
6 | |||
| isInformational | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| isSuccess | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| isRedirection | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| isClientError | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| isServerError | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| isError | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
| 1 | <?php |
| 2 | |
| 3 | declare(strict_types=1); |
| 4 | |
| 5 | /** |
| 6 | * This file is part of php-fast-forward/http-message. |
| 7 | * |
| 8 | * This source file is subject to the license bundled |
| 9 | * with this source code in the file LICENSE. |
| 10 | * |
| 11 | * @link https://github.com/php-fast-forward/http-message |
| 12 | * @copyright Copyright (c) 2025 Felipe Sayão Lobato Abreu <github@mentordosnerds.com> |
| 13 | * @license https://opensource.org/licenses/MIT MIT License |
| 14 | */ |
| 15 | |
| 16 | namespace FastForward\Http\Message; |
| 17 | |
| 18 | /** |
| 19 | * Enum StatusCode. |
| 20 | * |
| 21 | * Defines HTTP status codes in accordance with the IETF RFC 9110 and related specifications. |
| 22 | * This enum provides a structured representation of common HTTP response codes, grouped by their respective categories: |
| 23 | * |
| 24 | * - Informational (1xx) |
| 25 | * - Successful (2xx) |
| 26 | * - Redirection (3xx) |
| 27 | * - Client Errors (4xx) |
| 28 | * - Server Errors (5xx) |
| 29 | * |
| 30 | * All status codes MUST adhere to the official HTTP specification and SHALL be used consistently within HTTP responses. |
| 31 | * |
| 32 | * @package FastForward\Http\Message |
| 33 | */ |
| 34 | enum StatusCode: int |
| 35 | { |
| 36 | // Informational 1xx |
| 37 | |
| 38 | /** @var int The server has received the request headers and the client SHOULD proceed to send the request body. */ |
| 39 | case Continue = 100; |
| 40 | |
| 41 | /** @var int The requester has asked the server to switch protocols. */ |
| 42 | case SwitchingProtocols = 101; |
| 43 | |
| 44 | /** @var int The server has received and is processing the request, but no response is available yet. */ |
| 45 | case Processing = 102; |
| 46 | |
| 47 | /** @var int Used to return some response headers before the final HTTP message. */ |
| 48 | case EarlyHints = 103; |
| 49 | |
| 50 | // Successful 2xx |
| 51 | |
| 52 | /** @var int The request has succeeded. */ |
| 53 | case Ok = 200; |
| 54 | |
| 55 | /** @var int The request has been fulfilled and has resulted in the creation of a new resource. */ |
| 56 | case Created = 201; |
| 57 | |
| 58 | /** @var int The request has been accepted for processing, but the processing has not been completed. */ |
| 59 | case Accepted = 202; |
| 60 | |
| 61 | /** @var int The request was successful, but the enclosed payload has been modified from that of the origin server. */ |
| 62 | case NonAuthoritativeInformation = 203; |
| 63 | |
| 64 | /** @var int The server successfully processed the request and is not returning any content. */ |
| 65 | case NoContent = 204; |
| 66 | |
| 67 | /** @var int The server successfully processed the request, but is not returning any content, and requests that the requester reset the document view. */ |
| 68 | case ResetContent = 205; |
| 69 | |
| 70 | /** @var int The server is delivering only part of the resource due to a range header sent by the client. */ |
| 71 | case PartialContent = 206; |
| 72 | |
| 73 | /** @var int The message body that follows is an XML message and can contain a number of separate response codes. */ |
| 74 | case MultiStatus = 207; |
| 75 | |
| 76 | /** @var int The members of a DAV binding have already been enumerated in a previous reply to this request, and are not being included again. */ |
| 77 | case AlreadyReported = 208; |
| 78 | |
| 79 | /** @var int The server has fulfilled a request for the resource, and the response is a representation of the result of one or more instance-manipulations. */ |
| 80 | case ImUsed = 226; |
| 81 | |
| 82 | // Redirection 3xx |
| 83 | |
| 84 | /** @var int Indicates multiple options for the resource from which the client may choose. */ |
| 85 | case MultipleChoices = 300; |
| 86 | |
| 87 | /** @var int This and all future requests SHOULD be directed to the given URI. */ |
| 88 | case MovedPermanently = 301; |
| 89 | |
| 90 | /** @var int The resource resides temporarily under a different URI. */ |
| 91 | case Found = 302; |
| 92 | |
| 93 | /** @var int The response to the request can be found under another URI using a GET method. */ |
| 94 | case SeeOther = 303; |
| 95 | |
| 96 | /** @var int Indicates the resource has not been modified since the version specified by the request headers. */ |
| 97 | case NotModified = 304; |
| 98 | |
| 99 | /** @var int The requested resource is only available through a proxy, whose address is provided in the response. */ |
| 100 | case UseProxy = 305; |
| 101 | |
| 102 | /** @var int Reserved for future use. */ |
| 103 | case Reserved = 306; |
| 104 | |
| 105 | /** @var int Instructs the client to repeat the request with a different URI. */ |
| 106 | case TemporaryRedirect = 307; |
| 107 | |
| 108 | /** @var int The request and all future requests SHOULD be repeated using another URI. */ |
| 109 | case PermanentRedirect = 308; |
| 110 | |
| 111 | // Client Errors 4xx |
| 112 | |
| 113 | /** @var int The server cannot process the request due to a client error. */ |
| 114 | case BadRequest = 400; |
| 115 | |
| 116 | /** @var int Authentication is required and has failed or has not yet been provided. */ |
| 117 | case Unauthorized = 401; |
| 118 | |
| 119 | /** @var int Payment is required to access the requested resource. */ |
| 120 | case PaymentRequired = 402; |
| 121 | |
| 122 | /** @var int The client does not have permission to access the resource. */ |
| 123 | case Forbidden = 403; |
| 124 | |
| 125 | /** @var int The requested resource could not be found. */ |
| 126 | case NotFound = 404; |
| 127 | |
| 128 | /** @var int A request method is not supported for the requested resource. */ |
| 129 | case MethodNotAllowed = 405; |
| 130 | |
| 131 | /** @var int The requested resource is capable of generating only content not acceptable according to the Accept headers. */ |
| 132 | case NotAcceptable = 406; |
| 133 | |
| 134 | /** @var int Proxy authentication is required to access the resource. */ |
| 135 | case ProxyAuthenticationRequired = 407; |
| 136 | |
| 137 | /** @var int The client did not produce a request within the time that the server was prepared to wait. */ |
| 138 | case RequestTimeout = 408; |
| 139 | |
| 140 | /** @var int The request could not be completed due to a conflict with the current state of the resource. */ |
| 141 | case Conflict = 409; |
| 142 | |
| 143 | /** @var int The resource requested is no longer available and will not be available again. */ |
| 144 | case Gone = 410; |
| 145 | |
| 146 | /** @var int The request did not specify the length of its content, which is required by the requested resource. */ |
| 147 | case LengthRequired = 411; |
| 148 | |
| 149 | /** @var int The server does not meet one of the preconditions specified by the requester. */ |
| 150 | case PreconditionFailed = 412; |
| 151 | |
| 152 | /** @var int The request is larger than the server is willing or able to process. */ |
| 153 | case PayloadTooLarge = 413; |
| 154 | |
| 155 | /** @var int The URI provided was too long for the server to process. */ |
| 156 | case UriTooLong = 414; |
| 157 | |
| 158 | /** @var int The server does not support the media format of the requested data. */ |
| 159 | case UnsupportedMediaType = 415; |
| 160 | |
| 161 | /** @var int The client has asked for a portion of the file, but the server cannot supply that portion. */ |
| 162 | case RangeNotSatisfiable = 416; |
| 163 | |
| 164 | /** @var int The server cannot meet the expectations specified in the Expect request header. */ |
| 165 | case ExpectationFailed = 417; |
| 166 | |
| 167 | /** @var int This code is returned by HTCPCP-compliant teapots. */ |
| 168 | case ImATeapot = 418; |
| 169 | |
| 170 | /** @var int The request was directed at a server that is not able to produce a response. */ |
| 171 | case MisdirectedRequest = 421; |
| 172 | |
| 173 | /** @var int The request was well-formed but was unable to be followed due to semantic errors. */ |
| 174 | case UnprocessableEntity = 422; |
| 175 | |
| 176 | /** @var int The resource that is being accessed is locked. */ |
| 177 | case Locked = 423; |
| 178 | |
| 179 | /** @var int The request failed due to failure of a previous request. */ |
| 180 | case FailedDependency = 424; |
| 181 | |
| 182 | /** @var int Indicates the server is unwilling to risk processing a request that might be replayed. */ |
| 183 | case TooEarly = 425; |
| 184 | |
| 185 | /** @var int The client should switch to a different protocol such as TLS/1.0. */ |
| 186 | case UpgradeRequired = 426; |
| 187 | |
| 188 | /** @var int The origin server requires the request to be conditional. */ |
| 189 | case PreconditionRequired = 428; |
| 190 | |
| 191 | /** @var int The user has sent too many requests in a given amount of time. */ |
| 192 | case TooManyRequests = 429; |
| 193 | |
| 194 | /** @var int The server is unwilling to process the request because its header fields are too large. */ |
| 195 | case RequestHeaderFieldsTooLarge = 431; |
| 196 | |
| 197 | /** @var int The requested resource is unavailable for legal reasons. */ |
| 198 | case UnavailableForLegalReasons = 451; |
| 199 | |
| 200 | // Server Errors 5xx |
| 201 | |
| 202 | /** @var int The server encountered an unexpected condition that prevented it from fulfilling the request. */ |
| 203 | case InternalServerError = 500; |
| 204 | |
| 205 | /** @var int The server does not support the functionality required to fulfill the request. */ |
| 206 | case NotImplemented = 501; |
| 207 | |
| 208 | /** @var int The server, while acting as a gateway or proxy, received an invalid response from the upstream server. */ |
| 209 | case BadGateway = 502; |
| 210 | |
| 211 | /** @var int The server is currently unavailable due to maintenance or overload. */ |
| 212 | case ServiceUnavailable = 503; |
| 213 | |
| 214 | /** @var int The server did not receive a timely response from an upstream server. */ |
| 215 | case GatewayTimeout = 504; |
| 216 | |
| 217 | /** @var int The server does not support the HTTP protocol version used in the request. */ |
| 218 | case VersionNotSupported = 505; |
| 219 | |
| 220 | /** @var int Transparent content negotiation for the request results in a circular reference. */ |
| 221 | case VariantAlsoNegotiates = 506; |
| 222 | |
| 223 | /** @var int The server is unable to store the representation needed to complete the request. */ |
| 224 | case InsufficientStorage = 507; |
| 225 | |
| 226 | /** @var int The server detected an infinite loop while processing a request. */ |
| 227 | case LoopDetected = 508; |
| 228 | |
| 229 | /** @var int Further extensions to the request are required for the server to fulfill it. */ |
| 230 | case NotExtended = 510; |
| 231 | |
| 232 | /** @var int The client needs to authenticate to gain network access. */ |
| 233 | case NetworkAuthenticationRequired = 511; |
| 234 | |
| 235 | /** |
| 236 | * Returns the numeric HTTP status code. |
| 237 | * |
| 238 | * @return int the numeric status code as defined by the HTTP specification |
| 239 | */ |
| 240 | public function getCode(): int |
| 241 | { |
| 242 | return $this->value; |
| 243 | } |
| 244 | |
| 245 | /** |
| 246 | * Returns a human-readable description of the status code. |
| 247 | * |
| 248 | * The description is derived from the enum name, replacing underscores with spaces and capitalizing each word. |
| 249 | * |
| 250 | * @return string the reason phrase corresponding to the status code |
| 251 | */ |
| 252 | public function getReasonPhrase(): string |
| 253 | { |
| 254 | return preg_replace('/(?<!^)[A-Z]/', ' $0', $this->name); |
| 255 | } |
| 256 | |
| 257 | /** |
| 258 | * Returns the category of the status code. |
| 259 | * |
| 260 | * Categories are based on the first digit of the status code: |
| 261 | * - 1: Informational |
| 262 | * - 2: Success |
| 263 | * - 3: Redirection |
| 264 | * - 4: Client Error |
| 265 | * - 5: Server Error |
| 266 | */ |
| 267 | public function getCategory(): string |
| 268 | { |
| 269 | return match (intdiv($this->value, 100)) { |
| 270 | 1 => 'Informational', |
| 271 | 2 => 'Success', |
| 272 | 3 => 'Redirection', |
| 273 | 4 => 'Client Error', |
| 274 | 5 => 'Server Error', |
| 275 | }; |
| 276 | } |
| 277 | |
| 278 | /** |
| 279 | * Returns true if the status code is informational (1xx). |
| 280 | */ |
| 281 | public function isInformational(): bool |
| 282 | { |
| 283 | return 1 === intdiv($this->value, 100); |
| 284 | } |
| 285 | |
| 286 | /** |
| 287 | * Returns true if the status code indicates success (2xx). |
| 288 | */ |
| 289 | public function isSuccess(): bool |
| 290 | { |
| 291 | return 2 === intdiv($this->value, 100); |
| 292 | } |
| 293 | |
| 294 | /** |
| 295 | * Returns true if the status code indicates redirection (3xx). |
| 296 | */ |
| 297 | public function isRedirection(): bool |
| 298 | { |
| 299 | return 3 === intdiv($this->value, 100); |
| 300 | } |
| 301 | |
| 302 | /** |
| 303 | * Returns true if the status code indicates a client error (4xx). |
| 304 | */ |
| 305 | public function isClientError(): bool |
| 306 | { |
| 307 | return 4 === intdiv($this->value, 100); |
| 308 | } |
| 309 | |
| 310 | /** |
| 311 | * Returns true if the status code indicates a server error (5xx). |
| 312 | */ |
| 313 | public function isServerError(): bool |
| 314 | { |
| 315 | return 5 === intdiv($this->value, 100); |
| 316 | } |
| 317 | |
| 318 | /** |
| 319 | * Returns true if the status code indicates any type of error (client or server). |
| 320 | */ |
| 321 | public function isError(): bool |
| 322 | { |
| 323 | return $this->isClientError() || $this->isServerError(); |
| 324 | } |
| 325 | } |