_status_codes.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. from enum import IntEnum
  2. class codes(IntEnum):
  3. """HTTP status codes and reason phrases
  4. Status codes from the following RFCs are all observed:
  5. * RFC 7231: Hypertext Transfer Protocol (HTTP/1.1), obsoletes 2616
  6. * RFC 6585: Additional HTTP Status Codes
  7. * RFC 3229: Delta encoding in HTTP
  8. * RFC 4918: HTTP Extensions for WebDAV, obsoletes 2518
  9. * RFC 5842: Binding Extensions to WebDAV
  10. * RFC 7238: Permanent Redirect
  11. * RFC 2295: Transparent Content Negotiation in HTTP
  12. * RFC 2774: An HTTP Extension Framework
  13. * RFC 7540: Hypertext Transfer Protocol Version 2 (HTTP/2)
  14. * RFC 2324: Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0)
  15. * RFC 7725: An HTTP Status Code to Report Legal Obstacles
  16. * RFC 8297: An HTTP Status Code for Indicating Hints
  17. * RFC 8470: Using Early Data in HTTP
  18. """
  19. def __new__(cls, value: int, phrase: str = "") -> "codes":
  20. obj = int.__new__(cls, value)
  21. obj._value_ = value
  22. obj.phrase = phrase # type: ignore[attr-defined]
  23. return obj
  24. def __str__(self) -> str:
  25. return str(self.value)
  26. @classmethod
  27. def get_reason_phrase(cls, value: int) -> str:
  28. try:
  29. return codes(value).phrase # type: ignore
  30. except ValueError:
  31. return ""
  32. @classmethod
  33. def is_informational(cls, value: int) -> bool:
  34. """
  35. Returns `True` for 1xx status codes, `False` otherwise.
  36. """
  37. return 100 <= value <= 199
  38. @classmethod
  39. def is_success(cls, value: int) -> bool:
  40. """
  41. Returns `True` for 2xx status codes, `False` otherwise.
  42. """
  43. return 200 <= value <= 299
  44. @classmethod
  45. def is_redirect(cls, value: int) -> bool:
  46. """
  47. Returns `True` for 3xx status codes, `False` otherwise.
  48. """
  49. return 300 <= value <= 399
  50. @classmethod
  51. def is_client_error(cls, value: int) -> bool:
  52. """
  53. Returns `True` for 4xx status codes, `False` otherwise.
  54. """
  55. return 400 <= value <= 499
  56. @classmethod
  57. def is_server_error(cls, value: int) -> bool:
  58. """
  59. Returns `True` for 5xx status codes, `False` otherwise.
  60. """
  61. return 500 <= value <= 599
  62. @classmethod
  63. def is_error(cls, value: int) -> bool:
  64. """
  65. Returns `True` for 4xx or 5xx status codes, `False` otherwise.
  66. """
  67. return 400 <= value <= 599
  68. # informational
  69. CONTINUE = 100, "Continue"
  70. SWITCHING_PROTOCOLS = 101, "Switching Protocols"
  71. PROCESSING = 102, "Processing"
  72. EARLY_HINTS = 103, "Early Hints"
  73. # success
  74. OK = 200, "OK"
  75. CREATED = 201, "Created"
  76. ACCEPTED = 202, "Accepted"
  77. NON_AUTHORITATIVE_INFORMATION = 203, "Non-Authoritative Information"
  78. NO_CONTENT = 204, "No Content"
  79. RESET_CONTENT = 205, "Reset Content"
  80. PARTIAL_CONTENT = 206, "Partial Content"
  81. MULTI_STATUS = 207, "Multi-Status"
  82. ALREADY_REPORTED = 208, "Already Reported"
  83. IM_USED = 226, "IM Used"
  84. # redirection
  85. MULTIPLE_CHOICES = 300, "Multiple Choices"
  86. MOVED_PERMANENTLY = 301, "Moved Permanently"
  87. FOUND = 302, "Found"
  88. SEE_OTHER = 303, "See Other"
  89. NOT_MODIFIED = 304, "Not Modified"
  90. USE_PROXY = 305, "Use Proxy"
  91. TEMPORARY_REDIRECT = 307, "Temporary Redirect"
  92. PERMANENT_REDIRECT = 308, "Permanent Redirect"
  93. # client error
  94. BAD_REQUEST = 400, "Bad Request"
  95. UNAUTHORIZED = 401, "Unauthorized"
  96. PAYMENT_REQUIRED = 402, "Payment Required"
  97. FORBIDDEN = 403, "Forbidden"
  98. NOT_FOUND = 404, "Not Found"
  99. METHOD_NOT_ALLOWED = 405, "Method Not Allowed"
  100. NOT_ACCEPTABLE = 406, "Not Acceptable"
  101. PROXY_AUTHENTICATION_REQUIRED = 407, "Proxy Authentication Required"
  102. REQUEST_TIMEOUT = 408, "Request Timeout"
  103. CONFLICT = 409, "Conflict"
  104. GONE = 410, "Gone"
  105. LENGTH_REQUIRED = 411, "Length Required"
  106. PRECONDITION_FAILED = 412, "Precondition Failed"
  107. REQUEST_ENTITY_TOO_LARGE = 413, "Request Entity Too Large"
  108. REQUEST_URI_TOO_LONG = 414, "Request-URI Too Long"
  109. UNSUPPORTED_MEDIA_TYPE = 415, "Unsupported Media Type"
  110. REQUESTED_RANGE_NOT_SATISFIABLE = 416, "Requested Range Not Satisfiable"
  111. EXPECTATION_FAILED = 417, "Expectation Failed"
  112. IM_A_TEAPOT = 418, "I'm a teapot"
  113. MISDIRECTED_REQUEST = 421, "Misdirected Request"
  114. UNPROCESSABLE_ENTITY = 422, "Unprocessable Entity"
  115. LOCKED = 423, "Locked"
  116. FAILED_DEPENDENCY = 424, "Failed Dependency"
  117. TOO_EARLY = 425, "Too Early"
  118. UPGRADE_REQUIRED = 426, "Upgrade Required"
  119. PRECONDITION_REQUIRED = 428, "Precondition Required"
  120. TOO_MANY_REQUESTS = 429, "Too Many Requests"
  121. REQUEST_HEADER_FIELDS_TOO_LARGE = 431, "Request Header Fields Too Large"
  122. UNAVAILABLE_FOR_LEGAL_REASONS = 451, "Unavailable For Legal Reasons"
  123. # server errors
  124. INTERNAL_SERVER_ERROR = 500, "Internal Server Error"
  125. NOT_IMPLEMENTED = 501, "Not Implemented"
  126. BAD_GATEWAY = 502, "Bad Gateway"
  127. SERVICE_UNAVAILABLE = 503, "Service Unavailable"
  128. GATEWAY_TIMEOUT = 504, "Gateway Timeout"
  129. HTTP_VERSION_NOT_SUPPORTED = 505, "HTTP Version Not Supported"
  130. VARIANT_ALSO_NEGOTIATES = 506, "Variant Also Negotiates"
  131. INSUFFICIENT_STORAGE = 507, "Insufficient Storage"
  132. LOOP_DETECTED = 508, "Loop Detected"
  133. NOT_EXTENDED = 510, "Not Extended"
  134. NETWORK_AUTHENTICATION_REQUIRED = 511, "Network Authentication Required"
  135. # Include lower-case styles for `requests` compatibility.
  136. for code in codes:
  137. setattr(codes, code._name_.lower(), int(code))