Skip to content

Instantly share code, notes, and snippets.

@upadrian
Forked from aryelgois/HttpResponse.php
Last active January 3, 2023 22:52
Show Gist options
  • Select an option

  • Save upadrian/f6f642a86d2f0323ace0f64ab0bc24b0 to your computer and use it in GitHub Desktop.

Select an option

Save upadrian/f6f642a86d2f0323ace0f64ab0bc24b0 to your computer and use it in GitHub Desktop.
PHP Class for HTTP Response Status Codes
<?php
/**
* This Software is provided "as is" under the terms of the MIT license.
* @link https://opensource.org/licenses/MIT
*/
/**
* Provides named constants for HTTP protocol status codes and their messages
*
* - Originally written for the Recess Framework http://www.recessframework.com
* - Forked from https://gist.github.com/ewwink/f14474fd955801153c47
* - Forked from https://gist.github.com/aryelgois/e577aa73ebbe1463532ab8a584e3d16c
* - Adapted for general use
* - Adapted for my use
*
* Code beauty upadrian@2023
*
* @author Kris Jordan
* @author Aryel Mota Góis
* @author upadrian
* @license MIT
* @link https://gist.github.com/upadrian/f6f642a86d2f0323ace0f64ab0bc24b0
* @version 0.1.3
*/
class Http {
// Informational 1xx
const HTTP_CONTINUE = 100;
const HTTP_SWITCHING_PROTOCOLS = 101;
const HTTP_PROCESSING = 102;
const HTTP_CHECKPOINT = 103;
// Successful 2xx
const HTTP_OK = 200;
const HTTP_CREATED = 201;
const HTTP_ACCEPTED = 202;
const HTTP_NONAUTHORITATIVE_INFORMATION = 203;
const HTTP_NO_CONTENT = 204;
const HTTP_RESET_CONTENT = 205;
const HTTP_PARTIAL_CONTENT = 206;
const HTTP_MULTI_STATUS = 207;
const HTTP_ALREDY_REPORTED = 208;
// Redirection 3xx
const HTTP_MULTIPLE_CHOICES = 300;
const HTTP_MOVED_PERMANENTLY = 301;
const HTTP_FOUND = 302;
const HTTP_SEE_OTHER = 303;
const HTTP_NOT_MODIFIED = 304;
const HTTP_USE_PROXY = 305;
const HTTP_UNUSED = 306;
const HTTP_TEMPORARY_REDIRECT = 307;
const HTTP_PERMANENT_REDIRECT = 308;
const ERROR_CODES_START = 400;
// Client Error 4xx
const HTTP_BAD_REQUEST = 400;
const HTTP_UNAUTHORIZED = 401;
const HTTP_PAYMENT_REQUIRED = 402;
const HTTP_FORBIDDEN = 403;
const HTTP_NOT_FOUND = 404;
const HTTP_METHOD_NOT_ALLOWED = 405;
const HTTP_NOT_ACCEPTABLE = 406;
const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
const HTTP_REQUEST_TIMEOUT = 408;
const HTTP_CONFLICT = 409;
const HTTP_GONE = 410;
const HTTP_LENGTH_REQUIRED = 411;
const HTTP_PRECONDITION_FAILED = 412;
const HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
const HTTP_REQUEST_URI_TOO_LONG = 414;
const HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
const HTTP_EXPECTATION_FAILED = 417;
const HTTP_I_M_A_TEAPOT = 418;
const HTTP_UNPROCESSABLE_ENTITY = 422;
const HTTP_LOCKED = 423;
const HTTP_FAILED_DEPENDENCY = 424;
const HTTP_UNASSIGNED = 425;
const HTTP_UPGRADE_REQUIRED = 426;
const HTTP_PRECONDITION_REQUIRED = 428;
const HTTP_TOO_MANY_REQUESTS = 429;
const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431;
const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451;
// Server Error 5xx
const HTTP_INTERNAL_SERVER_ERROR = 500;
const HTTP_NOT_IMPLEMENTED = 501;
const HTTP_BAD_GATEWAY = 502;
const HTTP_SERVICE_UNAVAILABLE = 503;
const HTTP_GATEWAY_TIMEOUT = 504;
const HTTP_VERSION_NOT_SUPPORTED = 505;
const HTTP_VARIANT_ALSO_NEGOTIATES = 506;
const HTTP_INSUFFICIENT_STORAGE = 507;
const HTTP_LOOP_DETECTED = 508;
const HTTP_BANDWIDTH_LIMIT_EXCEEDED = 509;
const HTTP_NOT_EXTENDED = 510;
const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511;
const HTTP_NOT_UPDATED = 512;
/**
* Maps status codes to standard messages
* @var string[]
*/
protected static array $messages = [
// Informational 1xx
100 => 'Continue',
101 => 'Switching Protocols',
102 => 'Processing',
103 => 'Checkpoint',
// Successful 2xx
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
207 => 'Multi-Status (Multi-Status, WebDAV)',
208 => 'Already Reported (WebDAV)',
// Redirection 3xx
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
306 => '(Unused)',
307 => 'Temporary Redirect',
308 => 'Permanent Redirect',
// Client Error 4xx
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
418 => 'I\'m a teapot',
422 => 'Unprocessable Entity (WebDAV)',
423 => 'Locked (WebDAV)',
424 => 'Failed Dependency (WebDAV)',
425 => 'Unassigned',
426 => 'Upgrade Required',
428 => 'Precondition Required',
429 => 'Too Many Requests',
431 => 'Request Header Fields Too Large',
451 => 'Unavailable for Legal Reasons',
// Server Error 5xx
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
506 => 'Variant Also Negotiates',
507 => 'Insufficient Storage (WebDAV)',
508 => 'Loop Detected (WebDAV)',
509 => 'Bandwidth Limit Exceeded',
510 => 'Not Extended',
511 => 'Network Authentication Required',
512 => 'Not updated'
];
/**
* Returns HTTP header message from HTTP code
* @param integer $code
* @return string
* @throws Exception
*/
public static function getStatusCodeHeader(int $code): string {
if (!self::checkStatusCode($code)) {
throw new Exception("Http Status Code is invalid.");
}
return "HTTP/1.1 {$code} " . self::$messages[$code];
}
/**
* Send header to the browser
* @param integer $code HTTP status code
* @throws Exception
*/
public static function sendStatusCodeHeader(int $code) {
if (headers_sent()) {
throw new Exception("Headers or output already sent.");
}
header(self::getStatusCodeHeader($code));
}
/**
* Tells if a status code is a error code
* @param integer $code HTTP status code
* @return boolean
* @throws Exception
*/
public static function isError(int $code): bool {
if (!self::checkStatusCode($code)) {
throw new Exception("Http Status Code is invalid.");
}
return $code >= self::ERROR_CODES_START;
}
/**
* Checks if a HTTP response with given status code can have body
* True if not in 100s and not 204 NO CONTENT and not 304 NOT MODIFIED
* @param integer $code HTTP status code
* @return boolean
* @throws Exception
*/
public static function statusCodeCanHaveBody(int $code): bool {
if (!self::checkStatusCode($code)) {
throw new Exception("Http Status Code is invalid.");
}
return ($code < self::HTTP_CONTINUE || $code >= self::HTTP_OK)
&& $code != self::HTTP_NO_CONTENT
&& $code != self::HTTP_NOT_MODIFIED;
}
/**
* Send location header
* @param string $location
* @throws Exception
* @throws Exception
*/
public static function sendLocationHeader(string $location) {
if (headers_sent()) {
throw new Exception("Headers or output already sent.");
}
header("Location: {$location}");
}
/**
* Return true if status code is valid and exists
* @param integer $code
* @return bool
*/
private static function checkStatusCode(int $code): bool {
return isset(self::$messages[$code]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment