summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Dufresne <jon.dufresne@gmail.com>2015-01-13 11:29:07 -0800
committerTim Graham <timograham@gmail.com>2015-01-28 06:59:40 -0500
commit24b2bc635e23e4235f51095fbe099beec27a65c8 (patch)
tree5800921109f8f30dccc5ee62516796a35512b646
parent0f3ea8c0bc9c7f7f5e448b0b2137bc6351f5eae3 (diff)
Fixed #24137 -- Switched to HTTP reason phrases from Python stdlib.
-rw-r--r--django/core/handlers/wsgi.py3
-rw-r--r--django/http/response.py68
-rw-r--r--docs/ref/request-response.txt14
-rw-r--r--docs/releases/1.9.txt7
-rw-r--r--tests/responses/tests.py6
5 files changed, 26 insertions, 72 deletions
diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py
index 7c94758e86..3f69bfaaae 100644
--- a/django/core/handlers/wsgi.py
+++ b/django/core/handlers/wsgi.py
@@ -16,9 +16,6 @@ from django.utils.encoding import force_str, force_text
from django.utils.functional import cached_property
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')
# encode() and decode() expect the charset to be a native string.
diff --git a/django/http/response.py b/django/http/response.py
index 560e2ac7a5..50c7a0e04a 100644
--- a/django/http/response.py
+++ b/django/http/response.py
@@ -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.http import cookie_date
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
-# 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)
@@ -118,8 +55,7 @@ class HttpResponseBase(six.Iterator):
if reason is not None:
self.reason_phrase = reason
elif self.reason_phrase is None:
- self.reason_phrase = REASON_PHRASES.get(self.status_code,
- 'UNKNOWN STATUS CODE')
+ self.reason_phrase = responses.get(self.status_code, 'Unknown Status Code')
self._charset = charset
if content_type is None:
content_type = '%s; charset=%s' % (settings.DEFAULT_CONTENT_TYPE,
diff --git a/docs/ref/request-response.txt b/docs/ref/request-response.txt
index 41e6d3dcdc..ffe2bf4cd3 100644
--- a/docs/ref/request-response.txt
+++ b/docs/ref/request-response.txt
@@ -629,6 +629,13 @@ Attributes
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
This is always ``False``.
@@ -980,6 +987,13 @@ Attributes
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
This is always ``True``.
diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt
index e15c1d9b60..e51d3b0afe 100644
--- a/docs/releases/1.9.txt
+++ b/docs/releases/1.9.txt
@@ -171,6 +171,13 @@ Miscellaneous
* CSS and images in ``contrib.admin`` to support Internet Explorer 6 & 7 have
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:
Features deprecated in 1.9
diff --git a/tests/responses/tests.py b/tests/responses/tests.py
index 892c09b857..bf7a0e12ef 100644
--- a/tests/responses/tests.py
+++ b/tests/responses/tests.py
@@ -50,9 +50,9 @@ class HttpResponseBaseTests(SimpleTestCase):
class HttpResponseTests(SimpleTestCase):
def test_status_code(self):
- resp = HttpResponse(status=418)
- self.assertEqual(resp.status_code, 418)
- self.assertEqual(resp.reason_phrase, "I'M A TEAPOT")
+ resp = HttpResponse(status=503)
+ self.assertEqual(resp.status_code, 503)
+ self.assertEqual(resp.reason_phrase, "Service Unavailable")
def test_reason_phrase(self):
reason = "I'm an anarchist coffee pot on crack."