diff -r a82d7e028458 Lib/http/__init__.py --- a/Lib/http/__init__.py Mon Jun 16 19:26:56 2014 -0400 +++ b/Lib/http/__init__.py Tue Jun 17 11:59:44 2014 -0700 @@ -1,1 +1,119 @@ -# This directory is a Python package. +from enum import Enum +from collections import namedtuple + + +_Status = namedtuple('Status', ( + 'code', + 'name', + 'description', +)) + + +class Status(Enum): + # informational + CONTINUE = _Status(100, 'Continue', 'Request received, please continue') + SWITCHING_PROTOCOLS = _Status(101, 'Switching Protocols', + 'Switching to new protocol; obey Upgrade header') + PROCESSING = _Status(102, 'Processing', '') + + # success + OK = _Status(200, 'OK', '') + CREATED = _Status(201, 'Created', '') + ACCEPTED = _Status(202, 'Accepted', '') + NON_AUTHORITATIVE_INFORMATION = _Status(203, + 'Non-Authoritative Information', '') + NO_CONTENT = _Status(204, 'No Content', '') + RESET_CONTENT = _Status(205, 'Reset Content', '') + PARTIAL_CONTENT = _Status(206, 'Partial Content', '') + MULTI_STATUS = _Status(207, 'Multi-Status', '') + ALREADY_REPORTED = _Status(208, 'Already Reported', '') + IM_USED = _Status(226, 'IM Used', '') + + # redirection + MULTIPLE_CHOICES = _Status(300, 'Multiple Choices', '') + MOVED_PERMANENTLY = _Status(301, 'Moved Permanently', '') + FOUND = _Status(302, 'Found', '') + SEE_OTHER = _Status(303, 'See Other', '') + NOT_MODIFIED = _Status(304, 'Not Modified', '') + USE_PROXY = _Status(305, 'Use Proxy', '') + SWITCH_PROXY = _Status(306, 'Switch Proxy', '') + TEMPORARY_REDIRECT = _Status(307, 'Temporary Redirect', '') + PERMANENT_REDIRECT = _Status(308, 'Permanent Redirect', '') + + # client error + BAD_REQUEST = _Status(400, 'Bad Request', '') + UNAUTHORIZED = _Status(401, 'Unauthorized', '') + PAYMENT_REQUIRED = _Status(402, 'Payment Required', '') + FORBIDDEN = _Status(403, 'Forbidden', '') + NOT_FOUND = _Status(404, 'Not Found', '') + METHOD_NOT_ALLOWED = _Status(405, 'Method Not Allowed', '') + NOT_ACCEPTABLE = _Status(406, 'Not Acceptable', '') + PROXY_AUTHENTICATION_REQUIRED = _Status(407, + 'Proxy Authentication Required', '') + REQUEST_TIMEOUT = _Status(408, 'Request Timeout', '') + CONFLICT = _Status(409, 'Conflict', '') + GONE = _Status(410, 'Gone', '') + LENGTH_REQUIRED = _Status(411, 'Length Required', '') + PRECONDITION_FAILED = _Status(412, 'Precondition Failed', '') + REQUEST_ENTITY_TOO_LARGE = _Status(413, 'Request Entity Too Large', '') + REQUEST_URI_TOO_LONG = _Status(414, 'Request URI Too Long', '') + UNSUPPORTED_MEDIA_TYPE = _Status(415, 'Unsupported Media Type', '') + REQUEST_RANGE_NOT_SATISFIABLE = _Status(416, + 'Request Range Not Satisfiable', '') + EXPECTATION_FAILED = _Status(417, 'Expectation Failed', '') + IM_A_TEAPOT = _Status(418, 'I\'m a teapot', '') + AUTHENTICATION_TIMEOUT = _Status(419, 'Authentication Timeout', + '') # April fools! + METHOD_FAILURE = _Status(420, 'Method Failure', '') # Spring framework + UNPROCESSABLE_ENTITY = _Status(422, 'Unprocessable Entity', '') + LOCKED = _Status(423, 'Locked', '') + FAILED_DEPENDENCY = _Status(424, 'Failed Dependency', '') + UPGRADE_REQUIRED = _Status(426, 'Upgrade Required', '') + PRECONDITION_REQUIRED = _Status(428, 'Precondition Required', '') + TOO_MANY_REQUESTS = _Status(429, 'Too Many Requests', '') + REQUEST_HEADER_FIELD_TOO_LARGE = _Status(431, + 'Request Header Field Too Large', '') + LOGIN_TIMEOUT = _Status(440, 'Login Timeout', '') # Microsoft + NO_RESPONSE = _Status(444, 'No Response', '') # Nginx + RETRY_WITH = _Status(449, 'Retry With', '') # Microsoft + BLOCKED_BY_WINDOWS_PARENTAL_CONTROLS = _Status(450, + 'Blocked By Windows Parental Controls', '') # Microsoft + UNAVAILABLE_FOR_LEGAL_REASONS = _Status(451, + 'Unavailable For Legal Reasons', '') # draft + REQUEST_HEADER_TOO_LARGE = _Status(494, 'Request Header Too Large', + '') # Nginx + CERT_ERROR = _Status(495, 'Cert Error', '') # nginx + NO_CERT = _Status(496, 'No Cert', '') # nginx + HTTP_TO_HTTPS = _Status(497, 'HTTP To HTTPS', '') # nginx + CLIENT_CLOSED_REQUEST = _Status(499, 'Client Closed Request', '') # nginx + + # server errors + INTERNAL_SERVER_ERROR = _Status(500, 'Internal Server Error', '') + NOT_IMPLEMENTED = _Status(501, 'Not Implemented', '') + BAD_GATEWAY = _Status(502, 'Bad Gateway', '') + SERVICE_UNAVAILABLE = _Status(503, 'Service Unavailable', '') + GATEWAY_TIMEOUT = _Status(504, 'Gateway Timeout', '') + HTTP_VERSION_NOT_SUPPORTED = _Status(505, 'HTTP Version Not Supported', '') + VARIANTS_ALSO_NEGOTIATES = _Status(506, 'Variant Also Negotiates', '') + INSUFFICIENT_STORAGE = _Status(507, 'Insufficient Storage', '') + LOOP_DETECTED = _Status(508, 'Loop Detected', '') + BANDWIDTH_LIMIT_EXCEEDED = _Status(509, 'Bandwidth Limit Exceeded', '') + NOT_EXTENDED = _Status(510, 'Not Extended', '') + NETWORK_AUTHENTICATION_REQUIRED = _Status(511, + 'Network Authentication Required', '') + ORIGIN_ERROR = _Status(520, 'Origin Error', '') # cloudflare + WEB_SERVER_IS_DOWN = _Status(521, 'Web Server Is Down', '') # cloudflare + CONNECTON_TIMED_OUT = _Status(522, 'Connection Timed Out', '') # cloudflare + PROXY_DECLINED_REQUEST = _Status(523, + 'Proxy Declined Request', '') # cloudflare + A_TIMEOUT_OCCURRED = _Status(524, 'A Timeout Occurred', '') # cloudflare + NETWORK_READ_TIMEOUT_ERROR = _Status(598, + 'Network Read Timeout Error', '') + NETWORK_CONNECT_TIMEOUT_ERROR = _Status(599, + 'Network Connect Timeout Error', '') + + +HTTP_STATUS_DESCRIPTIONS = { + Status[k].value.code: Status[k].value.description + for k in Status.__members__ +} diff -r a82d7e028458 Lib/http/client.py --- a/Lib/http/client.py Mon Jun 16 19:26:56 2014 -0400 +++ b/Lib/http/client.py Tue Jun 17 11:59:44 2014 -0700 @@ -68,6 +68,7 @@ import email.parser import email.message +import http import io import os import socket @@ -91,121 +92,15 @@ _CS_REQ_STARTED = 'Request-started' _CS_REQ_SENT = 'Request-sent' -# status codes -# informational -CONTINUE = 100 -SWITCHING_PROTOCOLS = 101 -PROCESSING = 102 -# successful -OK = 200 -CREATED = 201 -ACCEPTED = 202 -NON_AUTHORITATIVE_INFORMATION = 203 -NO_CONTENT = 204 -RESET_CONTENT = 205 -PARTIAL_CONTENT = 206 -MULTI_STATUS = 207 -IM_USED = 226 +# hack to maintain backwards compatibility +for k in http.Status.__members__: + globals()[k] = http.Status[k].value.code -# redirection -MULTIPLE_CHOICES = 300 -MOVED_PERMANENTLY = 301 -FOUND = 302 -SEE_OTHER = 303 -NOT_MODIFIED = 304 -USE_PROXY = 305 -TEMPORARY_REDIRECT = 307 - -# client error -BAD_REQUEST = 400 -UNAUTHORIZED = 401 -PAYMENT_REQUIRED = 402 -FORBIDDEN = 403 -NOT_FOUND = 404 -METHOD_NOT_ALLOWED = 405 -NOT_ACCEPTABLE = 406 -PROXY_AUTHENTICATION_REQUIRED = 407 -REQUEST_TIMEOUT = 408 -CONFLICT = 409 -GONE = 410 -LENGTH_REQUIRED = 411 -PRECONDITION_FAILED = 412 -REQUEST_ENTITY_TOO_LARGE = 413 -REQUEST_URI_TOO_LONG = 414 -UNSUPPORTED_MEDIA_TYPE = 415 -REQUESTED_RANGE_NOT_SATISFIABLE = 416 -EXPECTATION_FAILED = 417 -UNPROCESSABLE_ENTITY = 422 -LOCKED = 423 -FAILED_DEPENDENCY = 424 -UPGRADE_REQUIRED = 426 -PRECONDITION_REQUIRED = 428 -TOO_MANY_REQUESTS = 429 -REQUEST_HEADER_FIELDS_TOO_LARGE = 431 - -# server error -INTERNAL_SERVER_ERROR = 500 -NOT_IMPLEMENTED = 501 -BAD_GATEWAY = 502 -SERVICE_UNAVAILABLE = 503 -GATEWAY_TIMEOUT = 504 -HTTP_VERSION_NOT_SUPPORTED = 505 -INSUFFICIENT_STORAGE = 507 -NOT_EXTENDED = 510 -NETWORK_AUTHENTICATION_REQUIRED = 511 - -# Mapping status codes to official W3C names +# another hack to maintain backwards compatibility responses = { - 100: 'Continue', - 101: 'Switching Protocols', - - 200: 'OK', - 201: 'Created', - 202: 'Accepted', - 203: 'Non-Authoritative Information', - 204: 'No Content', - 205: 'Reset Content', - 206: 'Partial Content', - - 300: 'Multiple Choices', - 301: 'Moved Permanently', - 302: 'Found', - 303: 'See Other', - 304: 'Not Modified', - 305: 'Use Proxy', - 306: '(Unused)', - 307: 'Temporary Redirect', - - 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', - 428: 'Precondition Required', - 429: 'Too Many Requests', - 431: 'Request Header Fields Too Large', - - 500: 'Internal Server Error', - 501: 'Not Implemented', - 502: 'Bad Gateway', - 503: 'Service Unavailable', - 504: 'Gateway Timeout', - 505: 'HTTP Version Not Supported', - 511: 'Network Authentication Required', + http.Status[k].value.code: http.Status[k].value.name + for k in http.Status.__members__ } # maximal amount of data to read at one time in _safe_read @@ -880,7 +775,7 @@ response = self.response_class(self.sock, method=self._method) (version, code, message) = response._read_status() - if code != 200: + if code != http.Status.OK.value.code: self.close() raise OSError("Tunnel connection failed: %d %s" % (code, message.strip())) diff -r a82d7e028458 Lib/http/server.py --- a/Lib/http/server.py Mon Jun 16 19:26:56 2014 -0400 +++ b/Lib/http/server.py Tue Jun 17 11:59:44 2014 -0700 @@ -583,78 +583,10 @@ # form {code: (shortmessage, longmessage)}. # See RFC 2616 and 6585. responses = { - 100: ('Continue', 'Request received, please continue'), - 101: ('Switching Protocols', - 'Switching to new protocol; obey Upgrade header'), - - 200: ('OK', 'Request fulfilled, document follows'), - 201: ('Created', 'Document created, URL follows'), - 202: ('Accepted', - 'Request accepted, processing continues off-line'), - 203: ('Non-Authoritative Information', 'Request fulfilled from cache'), - 204: ('No Content', 'Request fulfilled, nothing follows'), - 205: ('Reset Content', 'Clear input form for further input.'), - 206: ('Partial Content', 'Partial content follows.'), - - 300: ('Multiple Choices', - 'Object has several resources -- see URI list'), - 301: ('Moved Permanently', 'Object moved permanently -- see URI list'), - 302: ('Found', 'Object moved temporarily -- see URI list'), - 303: ('See Other', 'Object moved -- see Method and URL list'), - 304: ('Not Modified', - 'Document has not changed since given time'), - 305: ('Use Proxy', - 'You must use proxy specified in Location to access this ' - 'resource.'), - 307: ('Temporary Redirect', - 'Object moved temporarily -- see URI list'), - - 400: ('Bad Request', - 'Bad request syntax or unsupported method'), - 401: ('Unauthorized', - 'No permission -- see authorization schemes'), - 402: ('Payment Required', - 'No payment -- see charging schemes'), - 403: ('Forbidden', - 'Request forbidden -- authorization will not help'), - 404: ('Not Found', 'Nothing matches the given URI'), - 405: ('Method Not Allowed', - 'Specified method is invalid for this resource.'), - 406: ('Not Acceptable', 'URI not available in preferred format.'), - 407: ('Proxy Authentication Required', 'You must authenticate with ' - 'this proxy before proceeding.'), - 408: ('Request Timeout', 'Request timed out; try again later.'), - 409: ('Conflict', 'Request conflict.'), - 410: ('Gone', - 'URI no longer exists and has been permanently removed.'), - 411: ('Length Required', 'Client must specify Content-Length.'), - 412: ('Precondition Failed', 'Precondition in headers is false.'), - 413: ('Request Entity Too Large', 'Entity is too large.'), - 414: ('Request-URI Too Long', 'URI is too long.'), - 415: ('Unsupported Media Type', 'Entity body in unsupported format.'), - 416: ('Requested Range Not Satisfiable', - 'Cannot satisfy request range.'), - 417: ('Expectation Failed', - 'Expect condition could not be satisfied.'), - 428: ('Precondition Required', - 'The origin server requires the request to be conditional.'), - 429: ('Too Many Requests', 'The user has sent too many requests ' - 'in a given amount of time ("rate limiting").'), - 431: ('Request Header Fields Too Large', 'The server is unwilling to ' - 'process the request because its header fields are too large.'), - - 500: ('Internal Server Error', 'Server got itself in trouble'), - 501: ('Not Implemented', - 'Server does not support this operation'), - 502: ('Bad Gateway', 'Invalid responses from another server/proxy.'), - 503: ('Service Unavailable', - 'The server cannot process the request due to a high load'), - 504: ('Gateway Timeout', - 'The gateway server did not receive a timely response'), - 505: ('HTTP Version Not Supported', 'Cannot fulfill request.'), - 511: ('Network Authentication Required', - 'The client needs to authenticate to gain network access.'), - } + http.Status[k].value.code: (http.Status[k].value.name, + http.Status[k].value.description) + for k in http.Status.__members__ + } class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):