Fixed #24137 -- Switched to HTTP reason phrases from Python stdlib.
This commit is contained in:
parent
0f3ea8c0bc
commit
24b2bc635e
|
@ -16,9 +16,6 @@ from django.utils.encoding import force_str, force_text
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
|
||||||
# For backwards compatibility -- lots of code uses this in the wild!
|
|
||||||
from django.http.response import REASON_PHRASES as STATUS_CODE_TEXT # NOQA
|
|
||||||
|
|
||||||
logger = logging.getLogger('django.request')
|
logger = logging.getLogger('django.request')
|
||||||
|
|
||||||
# encode() and decode() expect the charset to be a native string.
|
# encode() and decode() expect the charset to be a native string.
|
||||||
|
|
|
@ -17,73 +17,10 @@ from django.utils import six, timezone
|
||||||
from django.utils.encoding import force_bytes, force_text, force_str, iri_to_uri
|
from django.utils.encoding import force_bytes, force_text, force_str, iri_to_uri
|
||||||
from django.utils.http import cookie_date
|
from django.utils.http import cookie_date
|
||||||
from django.utils.six.moves import map
|
from django.utils.six.moves import map
|
||||||
|
from django.utils.six.moves.http_client import responses
|
||||||
from django.utils.six.moves.urllib.parse import urlparse
|
from django.utils.six.moves.urllib.parse import urlparse
|
||||||
|
|
||||||
|
|
||||||
# See http://www.iana.org/assignments/http-status-codes
|
|
||||||
REASON_PHRASES = {
|
|
||||||
100: 'CONTINUE',
|
|
||||||
101: 'SWITCHING PROTOCOLS',
|
|
||||||
102: 'PROCESSING',
|
|
||||||
200: 'OK',
|
|
||||||
201: 'CREATED',
|
|
||||||
202: 'ACCEPTED',
|
|
||||||
203: 'NON-AUTHORITATIVE INFORMATION',
|
|
||||||
204: 'NO CONTENT',
|
|
||||||
205: 'RESET CONTENT',
|
|
||||||
206: 'PARTIAL CONTENT',
|
|
||||||
207: 'MULTI-STATUS',
|
|
||||||
208: 'ALREADY REPORTED',
|
|
||||||
226: 'IM USED',
|
|
||||||
300: 'MULTIPLE CHOICES',
|
|
||||||
301: 'MOVED PERMANENTLY',
|
|
||||||
302: 'FOUND',
|
|
||||||
303: 'SEE OTHER',
|
|
||||||
304: 'NOT MODIFIED',
|
|
||||||
305: 'USE PROXY',
|
|
||||||
306: 'RESERVED',
|
|
||||||
307: 'TEMPORARY REDIRECT',
|
|
||||||
308: 'PERMANENT 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',
|
|
||||||
418: "I'M A TEAPOT",
|
|
||||||
422: 'UNPROCESSABLE ENTITY',
|
|
||||||
423: 'LOCKED',
|
|
||||||
424: 'FAILED DEPENDENCY',
|
|
||||||
426: 'UPGRADE REQUIRED',
|
|
||||||
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',
|
|
||||||
506: 'VARIANT ALSO NEGOTIATES',
|
|
||||||
507: 'INSUFFICIENT STORAGE',
|
|
||||||
508: 'LOOP DETECTED',
|
|
||||||
510: 'NOT EXTENDED',
|
|
||||||
511: 'NETWORK AUTHENTICATION REQUIRED',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
_charset_from_content_type_re = re.compile(r';\s*charset=(?P<charset>[^\s;]+)', re.I)
|
_charset_from_content_type_re = re.compile(r';\s*charset=(?P<charset>[^\s;]+)', re.I)
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,8 +55,7 @@ class HttpResponseBase(six.Iterator):
|
||||||
if reason is not None:
|
if reason is not None:
|
||||||
self.reason_phrase = reason
|
self.reason_phrase = reason
|
||||||
elif self.reason_phrase is None:
|
elif self.reason_phrase is None:
|
||||||
self.reason_phrase = REASON_PHRASES.get(self.status_code,
|
self.reason_phrase = responses.get(self.status_code, 'Unknown Status Code')
|
||||||
'UNKNOWN STATUS CODE')
|
|
||||||
self._charset = charset
|
self._charset = charset
|
||||||
if content_type is None:
|
if content_type is None:
|
||||||
content_type = '%s; charset=%s' % (settings.DEFAULT_CONTENT_TYPE,
|
content_type = '%s; charset=%s' % (settings.DEFAULT_CONTENT_TYPE,
|
||||||
|
|
|
@ -629,6 +629,13 @@ Attributes
|
||||||
|
|
||||||
The HTTP reason phrase for the response.
|
The HTTP reason phrase for the response.
|
||||||
|
|
||||||
|
.. versionchanged:: 1.9
|
||||||
|
|
||||||
|
``reason_phrase`` no longer defaults to all capital letters. It now
|
||||||
|
uses the `HTTP standard's`_ default reason phrases.
|
||||||
|
|
||||||
|
.. _`HTTP standard's`: https://www.ietf.org/rfc/rfc2616.txt
|
||||||
|
|
||||||
.. attribute:: HttpResponse.streaming
|
.. attribute:: HttpResponse.streaming
|
||||||
|
|
||||||
This is always ``False``.
|
This is always ``False``.
|
||||||
|
@ -980,6 +987,13 @@ Attributes
|
||||||
|
|
||||||
The HTTP reason phrase for the response.
|
The HTTP reason phrase for the response.
|
||||||
|
|
||||||
|
.. versionchanged:: 1.9
|
||||||
|
|
||||||
|
``reason_phrase`` no longer defaults to all capital letters. It now
|
||||||
|
uses the `HTTP standard's`_ default reason phrases.
|
||||||
|
|
||||||
|
.. _`HTTP standard's`: https://www.ietf.org/rfc/rfc2616.txt
|
||||||
|
|
||||||
.. attribute:: StreamingHttpResponse.streaming
|
.. attribute:: StreamingHttpResponse.streaming
|
||||||
|
|
||||||
This is always ``True``.
|
This is always ``True``.
|
||||||
|
|
|
@ -171,6 +171,13 @@ Miscellaneous
|
||||||
* CSS and images in ``contrib.admin`` to support Internet Explorer 6 & 7 have
|
* CSS and images in ``contrib.admin`` to support Internet Explorer 6 & 7 have
|
||||||
been removed as these browsers have reached end-of-life.
|
been removed as these browsers have reached end-of-life.
|
||||||
|
|
||||||
|
* ``django.http.responses.REASON_PHRASES`` and
|
||||||
|
``django.core.handlers.wsgi.STATUS_CODE_TEXT`` have been removed. Use
|
||||||
|
Python's stdlib instead: :data:`http.client.responses` for Python 3 and
|
||||||
|
`httplib.responses`_ for Python 2.
|
||||||
|
|
||||||
|
.. _`httplib.responses`: https://docs.python.org/2/library/httplib.html#httplib.responses
|
||||||
|
|
||||||
.. _deprecated-features-1.9:
|
.. _deprecated-features-1.9:
|
||||||
|
|
||||||
Features deprecated in 1.9
|
Features deprecated in 1.9
|
||||||
|
|
|
@ -50,9 +50,9 @@ class HttpResponseBaseTests(SimpleTestCase):
|
||||||
|
|
||||||
class HttpResponseTests(SimpleTestCase):
|
class HttpResponseTests(SimpleTestCase):
|
||||||
def test_status_code(self):
|
def test_status_code(self):
|
||||||
resp = HttpResponse(status=418)
|
resp = HttpResponse(status=503)
|
||||||
self.assertEqual(resp.status_code, 418)
|
self.assertEqual(resp.status_code, 503)
|
||||||
self.assertEqual(resp.reason_phrase, "I'M A TEAPOT")
|
self.assertEqual(resp.reason_phrase, "Service Unavailable")
|
||||||
|
|
||||||
def test_reason_phrase(self):
|
def test_reason_phrase(self):
|
||||||
reason = "I'm an anarchist coffee pot on crack."
|
reason = "I'm an anarchist coffee pot on crack."
|
||||||
|
|
Loading…
Reference in New Issue