1 module hunt.http.codec.http.model.HttpStatus; 2 3 import hunt.util.traits; 4 import std.conv; 5 import std.format; 6 7 alias HttpStatusCode = HttpStatus.Code; 8 9 /** 10 * <p> 11 * Http Status Codes 12 * </p> 13 * 14 * @see <a href="http://www.iana.org/assignments/http-status-codes/">IANA HTTP 15 * Status Code Registry</a> 16 */ 17 class HttpStatus { 18 enum CONTINUE_100 = 100; 19 enum SWITCHING_PROTOCOLS_101 = 101; 20 enum PROCESSING_102 = 102; 21 22 enum OK_200 = 200; 23 enum CREATED_201 = 201; 24 enum ACCEPTED_202 = 202; 25 enum NON_AUTHORITATIVE_INFORMATION_203 = 203; 26 enum NO_CONTENT_204 = 204; 27 enum RESET_CONTENT_205 = 205; 28 enum PARTIAL_CONTENT_206 = 206; 29 enum MULTI_STATUS_207 = 207; 30 31 enum MULTIPLE_CHOICES_300 = 300; 32 enum MOVED_PERMANENTLY_301 = 301; 33 enum MOVED_TEMPORARILY_302 = 302; 34 enum FOUND_302 = 302; 35 enum SEE_OTHER_303 = 303; 36 enum NOT_MODIFIED_304 = 304; 37 enum USE_PROXY_305 = 305; 38 enum TEMPORARY_REDIRECT_307 = 307; 39 enum PERMANENT_REDIRECT_308 = 308; 40 41 enum BAD_REQUEST_400 = 400; 42 enum UNAUTHORIZED_401 = 401; 43 enum PAYMENT_REQUIRED_402 = 402; 44 enum FORBIDDEN_403 = 403; 45 enum NOT_FOUND_404 = 404; 46 enum METHOD_NOT_ALLOWED_405 = 405; 47 enum NOT_ACCEPTABLE_406 = 406; 48 enum PROXY_AUTHENTICATION_REQUIRED_407 = 407; 49 enum REQUEST_TIMEOUT_408 = 408; 50 enum CONFLICT_409 = 409; 51 enum GONE_410 = 410; 52 enum LENGTH_REQUIRED_411 = 411; 53 enum PRECONDITION_FAILED_412 = 412; 54 deprecated("") 55 enum REQUEST_ENTITY_TOO_LARGE_413 = 413; 56 enum PAYLOAD_TOO_LARGE_413 = 413; 57 deprecated("") 58 enum REQUEST_URI_TOO_LONG_414 = 414; 59 enum URI_TOO_LONG_414 = 414; 60 enum UNSUPPORTED_MEDIA_TYPE_415 = 415; 61 deprecated("") 62 enum REQUESTED_RANGE_NOT_SATISFIABLE_416 = 416; 63 enum RANGE_NOT_SATISFIABLE_416 = 416; 64 enum EXPECTATION_FAILED_417 = 417; 65 enum IM_A_TEAPOT_418 = 418; 66 enum ENHANCE_YOUR_CALM_420 = 420; 67 enum MISDIRECTED_REQUEST_421 = 421; 68 enum UNPROCESSABLE_ENTITY_422 = 422; 69 enum LOCKED_423 = 423; 70 enum FAILED_DEPENDENCY_424 = 424; 71 enum UPGRADE_REQUIRED_426 = 426; 72 enum PRECONDITION_REQUIRED_428 = 428; 73 enum TOO_MANY_REQUESTS_429 = 429; 74 enum REQUEST_HEADER_FIELDS_TOO_LARGE_431 = 431; 75 enum UNAVAILABLE_FOR_LEGAL_REASONS_451 = 451; 76 77 enum INTERNAL_SERVER_ERROR_500 = 500; 78 enum NOT_IMPLEMENTED_501 = 501; 79 enum BAD_GATEWAY_502 = 502; 80 enum SERVICE_UNAVAILABLE_503 = 503; 81 enum GATEWAY_TIMEOUT_504 = 504; 82 enum HTTP_VERSION_NOT_SUPPORTED_505 = 505; 83 enum INSUFFICIENT_STORAGE_507 = 507; 84 enum LOOP_DETECTED_508 = 508; 85 enum NOT_EXTENDED_510 = 510; 86 enum NETWORK_AUTHENTICATION_REQUIRED_511 = 511; 87 88 enum MAX_CODE = 511 + 1; 89 90 private __gshared Code[] codeMap; // = new Code[MAX_CODE + 1]; 91 92 shared static this() { 93 codeMap = new Code[MAX_CODE + 1]; 94 foreach (Code code ; Code.values()) { 95 codeMap[code._code] = code; 96 } 97 } 98 99 struct Code { 100 enum Code Null = Code(MAX_CODE, ""); 101 enum Code CONTINUE = Code(CONTINUE_100, "Continue"); 102 enum Code SWITCHING_PROTOCOLS = Code(SWITCHING_PROTOCOLS_101, "Switching Protocols"); 103 enum Code PROCESSING = Code(PROCESSING_102, "Processing"); 104 105 106 enum Code OK = Code(OK_200, "OK"); 107 enum Code CREATED = Code(CREATED_201, "Created"); 108 enum Code ACCEPTED = Code(ACCEPTED_202, "Accepted"); 109 enum Code NON_AUTHORITATIVE_INFORMATION = Code(NON_AUTHORITATIVE_INFORMATION_203, "Non Authoritative Information"); 110 enum Code NO_CONTENT = Code(NO_CONTENT_204, "No Content"); 111 enum Code RESET_CONTENT = Code(RESET_CONTENT_205, "Reset Content"); 112 enum Code PARTIAL_CONTENT = Code(PARTIAL_CONTENT_206, "Partial Content"); 113 enum Code MULTI_STATUS = Code(MULTI_STATUS_207, "Multi-Status"); 114 115 enum Code MULTIPLE_CHOICES = Code(MULTIPLE_CHOICES_300, "Multiple Choices"); 116 enum Code MOVED_PERMANENTLY = Code(MOVED_PERMANENTLY_301, "Moved Permanently"); 117 enum Code MOVED_TEMPORARILY = Code(MOVED_TEMPORARILY_302, "Moved Temporarily"); 118 enum Code FOUND = Code(FOUND_302, "Found"); 119 enum Code SEE_OTHER = Code(SEE_OTHER_303, "See Other"); 120 enum Code NOT_MODIFIED = Code(NOT_MODIFIED_304, "Not Modified"); 121 enum Code USE_PROXY = Code(USE_PROXY_305, "Use Proxy"); 122 enum Code TEMPORARY_REDIRECT = Code(TEMPORARY_REDIRECT_307, "Temporary Redirect"); 123 enum Code PERMANET_REDIRECT = Code(PERMANENT_REDIRECT_308, "Permanent Redirect"); 124 125 enum Code BAD_REQUEST = Code(BAD_REQUEST_400, "Bad Request"); 126 enum Code UNAUTHORIZED = Code(UNAUTHORIZED_401, "Unauthorized"); 127 enum Code PAYMENT_REQUIRED = Code(PAYMENT_REQUIRED_402, "Payment Required"); 128 enum Code FORBIDDEN = Code(FORBIDDEN_403, "Forbidden"); 129 enum Code NOT_FOUND = Code(NOT_FOUND_404, "Not Found"); 130 enum Code METHOD_NOT_ALLOWED = Code(METHOD_NOT_ALLOWED_405, "Method Not Allowed"); 131 enum Code NOT_ACCEPTABLE = Code(NOT_ACCEPTABLE_406, "Not Acceptable"); 132 enum Code PROXY_AUTHENTICATION_REQUIRED = Code(PROXY_AUTHENTICATION_REQUIRED_407, "Proxy Authentication Required"); 133 enum Code REQUEST_TIMEOUT = Code(REQUEST_TIMEOUT_408, "Request Timeout"); 134 enum Code CONFLICT = Code(CONFLICT_409, "Conflict"); 135 enum Code GONE = Code(GONE_410, "Gone"); 136 enum Code LENGTH_REQUIRED = Code(LENGTH_REQUIRED_411, "Length Required"); 137 enum Code PRECONDITION_FAILED = Code(PRECONDITION_FAILED_412, "Precondition Failed"); 138 enum Code PAYLOAD_TOO_LARGE = Code(PAYLOAD_TOO_LARGE_413, "Payload Too Large"); 139 enum Code URI_TOO_LONG = Code(URI_TOO_LONG_414, "URI Too Long"); 140 enum Code UNSUPPORTED_MEDIA_TYPE = Code(UNSUPPORTED_MEDIA_TYPE_415, "Unsupported Media Type"); 141 enum Code RANGE_NOT_SATISFIABLE = Code(RANGE_NOT_SATISFIABLE_416, "Range Not Satisfiable"); 142 enum Code EXPECTATION_FAILED = Code(EXPECTATION_FAILED_417, "Expectation Failed"); 143 enum Code IM_A_TEAPOT = Code(IM_A_TEAPOT_418, "I'm a Teapot"); 144 enum Code ENHANCE_YOUR_CALM = Code(ENHANCE_YOUR_CALM_420, "Enhance your Calm"); 145 enum Code MISDIRECTED_REQUEST = Code(MISDIRECTED_REQUEST_421, "Misdirected Request"); 146 enum Code UNPROCESSABLE_ENTITY = Code(UNPROCESSABLE_ENTITY_422, "Unprocessable Entity"); 147 enum Code LOCKED = Code(LOCKED_423, "Locked"); 148 enum Code FAILED_DEPENDENCY = Code(FAILED_DEPENDENCY_424, "Failed Dependency"); 149 enum Code UPGRADE_REQUIRED = Code(UPGRADE_REQUIRED_426, "Upgrade Required"); 150 enum Code PRECONDITION_REQUIRED = Code(PRECONDITION_REQUIRED_428, "Precondition Required"); 151 enum Code TOO_MANY_REQUESTS = Code(TOO_MANY_REQUESTS_429, "Too Many Requests"); 152 enum Code REQUEST_HEADER_FIELDS_TOO_LARGE = Code(REQUEST_HEADER_FIELDS_TOO_LARGE_431, "Request Header Fields Too Large"); 153 enum Code UNAVAILABLE_FOR_LEGAL_REASONS = Code(UNAVAILABLE_FOR_LEGAL_REASONS_451, "Unavailable for Legal Reason"); 154 155 enum Code INTERNAL_SERVER_ERROR = Code(INTERNAL_SERVER_ERROR_500, "Server Error"); 156 enum Code NOT_IMPLEMENTED = Code(NOT_IMPLEMENTED_501, "Not Implemented"); 157 enum Code BAD_GATEWAY = Code(BAD_GATEWAY_502, "Bad Gateway"); 158 enum Code SERVICE_UNAVAILABLE = Code(SERVICE_UNAVAILABLE_503, "Service Unavailable"); 159 enum Code GATEWAY_TIMEOUT = Code(GATEWAY_TIMEOUT_504, "Gateway Timeout"); 160 enum Code HTTP_VERSION_NOT_SUPPORTED = Code(HTTP_VERSION_NOT_SUPPORTED_505, "HTTP Version Not Supported"); 161 enum Code INSUFFICIENT_STORAGE = Code(INSUFFICIENT_STORAGE_507, "Insufficient Storage"); 162 enum Code LOOP_DETECTED = Code(LOOP_DETECTED_508, "Loop Detected"); 163 enum Code NOT_EXTENDED = Code(NOT_EXTENDED_510, "Not Extended"); 164 enum Code NETWORK_AUTHENTICATION_REQUIRED = Code(NETWORK_AUTHENTICATION_REQUIRED_511, "Network Authentication Required"); 165 166 167 private int _code; 168 private string _message; 169 170 private this(int code, string message) { 171 this._code = code; 172 _message = message; 173 } 174 175 mixin GetConstantValues!(Code); 176 177 int getCode() { 178 return _code; 179 } 180 181 string getMessage() { 182 return _message; 183 } 184 185 bool equals(int code) { 186 return (this._code == code); 187 } 188 189 string toString() { 190 return format("[%03d %s]", this._code, this._message); 191 } 192 193 /** 194 * Simple test against an code to determine if it falls into the 195 * <code>Informational</code> message category as defined in the 196 * <a href="http://tools.ietf.org/html/rfc1945">RFC 1945 - HTTP/1.0</a>, 197 * and <a href="http://tools.ietf.org/html/rfc7231">RFC 7231 - 198 * HTTP/1.1</a>. 199 * 200 * @return true if within range of codes that belongs to 201 * <code>Informational</code> messages. 202 */ 203 bool isInformational() { 204 return HttpStatus.isInformational(this._code); 205 } 206 207 /** 208 * Simple test against an code to determine if it falls into the 209 * <code>Success</code> message category as defined in the 210 * <a href="http://tools.ietf.org/html/rfc1945">RFC 1945 - HTTP/1.0</a>, 211 * and <a href="http://tools.ietf.org/html/rfc7231">RFC 7231 - 212 * HTTP/1.1</a>. 213 * 214 * @return true if within range of codes that belongs to 215 * <code>Success</code> messages. 216 */ 217 bool isSuccess() { 218 return HttpStatus.isSuccess(this._code); 219 } 220 221 /** 222 * Simple test against an code to determine if it falls into the 223 * <code>Redirection</code> message category as defined in the 224 * <a href="http://tools.ietf.org/html/rfc1945">RFC 1945 - HTTP/1.0</a>, 225 * and <a href="http://tools.ietf.org/html/rfc7231">RFC 7231 - 226 * HTTP/1.1</a>. 227 * 228 * @return true if within range of codes that belongs to 229 * <code>Redirection</code> messages. 230 */ 231 bool isRedirection() { 232 return HttpStatus.isRedirection(this._code); 233 } 234 235 /** 236 * Simple test against an code to determine if it falls into the 237 * <code>Client Error</code> message category as defined in the 238 * <a href="http://tools.ietf.org/html/rfc1945">RFC 1945 - HTTP/1.0</a>, 239 * and <a href="http://tools.ietf.org/html/rfc7231">RFC 7231 - 240 * HTTP/1.1</a>. 241 * 242 * @return true if within range of codes that belongs to 243 * <code>Client Error</code> messages. 244 */ 245 bool isClientError() { 246 return HttpStatus.isClientError(this._code); 247 } 248 249 /** 250 * Simple test against an code to determine if it falls into the 251 * <code>Server Error</code> message category as defined in the 252 * <a href="http://tools.ietf.org/html/rfc1945">RFC 1945 - HTTP/1.0</a>, 253 * and <a href="http://tools.ietf.org/html/rfc7231">RFC 7231 - 254 * HTTP/1.1</a>. 255 * 256 * @return true if within range of codes that belongs to 257 * <code>Server Error</code> messages. 258 */ 259 bool isServerError() { 260 return HttpStatus.isServerError(this._code); 261 } 262 } 263 264 /** 265 * Get the HttpStatusCode for a specific code 266 * 267 * @param code 268 * the code to lookup. 269 * @return the {@link HttpStatus} if found, or null if not found. 270 */ 271 static Code getCode(int code) { 272 if (code <= MAX_CODE) { 273 return codeMap[code]; 274 } 275 return Code.Null; 276 } 277 278 /** 279 * Get the status message for a specific code. 280 * 281 * @param code 282 * the code to look up 283 * @return the specific message, or the code number itself if code does not 284 * match known list. 285 */ 286 static string getMessage(int code) { 287 Code codeEnum = getCode(code); 288 if (codeEnum != Code.Null) { 289 return codeEnum.getMessage(); 290 } else { 291 return std.conv.to!(string)(code); 292 } 293 } 294 295 /** 296 * Simple test against an code to determine if it falls into the 297 * <code>Informational</code> message category as defined in the 298 * <a href="http://tools.ietf.org/html/rfc1945">RFC 1945 - HTTP/1.0</a>, and 299 * <a href="http://tools.ietf.org/html/rfc7231">RFC 7231 - HTTP/1.1</a>. 300 * 301 * @param code 302 * the code to test. 303 * @return true if within range of codes that belongs to 304 * <code>Informational</code> messages. 305 */ 306 static bool isInformational(int code) { 307 return ((100 <= code) && (code <= 199)); 308 } 309 310 /** 311 * Simple test against an code to determine if it falls into the 312 * <code>Success</code> message category as defined in the 313 * <a href="http://tools.ietf.org/html/rfc1945">RFC 1945 - HTTP/1.0</a>, and 314 * <a href="http://tools.ietf.org/html/rfc7231">RFC 7231 - HTTP/1.1</a>. 315 * 316 * @param code 317 * the code to test. 318 * @return true if within range of codes that belongs to 319 * <code>Success</code> messages. 320 */ 321 static bool isSuccess(int code) { 322 return ((200 <= code) && (code <= 299)); 323 } 324 325 /** 326 * Simple test against an code to determine if it falls into the 327 * <code>Redirection</code> message category as defined in the 328 * <a href="http://tools.ietf.org/html/rfc1945">RFC 1945 - HTTP/1.0</a>, and 329 * <a href="http://tools.ietf.org/html/rfc7231">RFC 7231 - HTTP/1.1</a>. 330 * 331 * @param code 332 * the code to test. 333 * @return true if within range of codes that belongs to 334 * <code>Redirection</code> messages. 335 */ 336 static bool isRedirection(int code) { 337 return ((300 <= code) && (code <= 399)); 338 } 339 340 /** 341 * Simple test against an code to determine if it falls into the 342 * <code>Client Error</code> message category as defined in the 343 * <a href="http://tools.ietf.org/html/rfc1945">RFC 1945 - HTTP/1.0</a>, and 344 * <a href="http://tools.ietf.org/html/rfc7231">RFC 7231 - HTTP/1.1</a>. 345 * 346 * @param code 347 * the code to test. 348 * @return true if within range of codes that belongs to 349 * <code>Client Error</code> messages. 350 */ 351 static bool isClientError(int code) { 352 return ((400 <= code) && (code <= 499)); 353 } 354 355 /** 356 * Simple test against an code to determine if it falls into the 357 * <code>Server Error</code> message category as defined in the 358 * <a href="http://tools.ietf.org/html/rfc1945">RFC 1945 - HTTP/1.0</a>, and 359 * <a href="http://tools.ietf.org/html/rfc7231">RFC 7231 - HTTP/1.1</a>. 360 * 361 * @param code 362 * the code to test. 363 * @return true if within range of codes that belongs to 364 * <code>Server Error</code> messages. 365 */ 366 static bool isServerError(int code) { 367 return ((500 <= code) && (code <= 599)); 368 } 369 }