Loading django/core/handlers/wsgi.py +4 −63 Original line number Diff line number Diff line Loading @@ -13,66 +13,11 @@ from django.core.urlresolvers import set_script_prefix from django.utils import datastructures from django.utils.encoding import force_str, force_text, iri_to_uri logger = logging.getLogger('django.request') # For backwards compatibility -- lots of code uses this in the wild! from django.http.response import REASON_PHRASES as STATUS_CODE_TEXT logger = logging.getLogger('django.request') # See http://www.iana.org/assignments/http-status-codes STATUS_CODE_TEXT = { 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', 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', 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', } class LimitedStream(object): ''' Loading Loading @@ -254,11 +199,7 @@ class WSGIHandler(base.BaseHandler): response._handler_class = self.__class__ try: status_text = STATUS_CODE_TEXT[response.status_code] except KeyError: status_text = 'UNKNOWN STATUS CODE' status = '%s %s' % (response.status_code, status_text) status = '%s %s' % (response.status_code, response.reason_phrase) response_headers = [(str(k), str(v)) for k, v in response.items()] for c in response.cookies.values(): response_headers.append((str('Set-Cookie'), str(c.output(header='')))) Loading django/http/response.py +67 −3 Original line number Diff line number Diff line Loading @@ -20,6 +20,65 @@ from django.utils.http import cookie_date from django.utils.six.moves import map # 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', 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', 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', } class BadHeaderError(ValueError): pass Loading @@ -33,8 +92,9 @@ class HttpResponseBase(six.Iterator): """ status_code = 200 reason_phrase = None # Use default reason phrase for status code. def __init__(self, content_type=None, status=None, mimetype=None): def __init__(self, content_type=None, status=None, reason=None, mimetype=None): # _headers is a mapping of the lower-case name to the original case of # the header (required for working with legacy systems) and the header # value. Both the name of the header and its value are ASCII strings. Loading @@ -53,9 +113,13 @@ class HttpResponseBase(six.Iterator): content_type = "%s; charset=%s" % (settings.DEFAULT_CONTENT_TYPE, self._charset) self.cookies = SimpleCookie() if status: if status is not None: self.status_code = status 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['Content-Type'] = content_type def serialize_headers(self): Loading docs/ref/request-response.txt +21 −6 Original line number Diff line number Diff line Loading @@ -616,7 +616,13 @@ Attributes .. attribute:: HttpResponse.status_code The `HTTP Status code`_ for the response. The `HTTP status code`_ for the response. .. attribute:: HttpResponse.reason_phrase .. versionadded:: 1.6 The HTTP reason phrase for the response. .. attribute:: HttpResponse.streaming Loading @@ -628,7 +634,7 @@ Attributes Methods ------- .. method:: HttpResponse.__init__(content='', content_type=None, status=200) .. method:: HttpResponse.__init__(content='', content_type=None, status=200, reason=None) Instantiates an ``HttpResponse`` object with the given page content and content type. Loading @@ -646,8 +652,12 @@ Methods Historically, this parameter was called ``mimetype`` (now deprecated). ``status`` is the `HTTP Status code`_ for the response. ``status`` is the `HTTP status code`_ for the response. .. versionadded:: 1.6 ``reason`` is the HTTP response phrase. If not provided, a default phrase will be used. .. method:: HttpResponse.__setitem__(header, value) Loading Loading @@ -727,8 +737,7 @@ Methods This method makes an :class:`HttpResponse` instance a file-like object. .. _HTTP Status code: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10 .. _HTTP status code: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10 .. _ref-httpresponse-subclasses: Loading Loading @@ -851,7 +860,13 @@ Attributes .. attribute:: HttpResponse.status_code The `HTTP Status code`_ for the response. The `HTTP status code`_ for the response. .. attribute:: HttpResponse.reason_phrase .. versionadded:: 1.6 The HTTP reason phrase for the response. .. attribute:: HttpResponse.streaming Loading docs/releases/1.6.txt +2 −0 Original line number Diff line number Diff line Loading @@ -241,6 +241,8 @@ Minor features * The ``choices`` argument to model fields now accepts an iterable of iterables instead of requiring an iterable of lists or tuples. * The reason phrase can be customized in HTTP responses. Backwards incompatible changes in 1.6 ===================================== Loading tests/responses/__init__.py 0 → 100644 +0 −0 Empty file added. Loading
django/core/handlers/wsgi.py +4 −63 Original line number Diff line number Diff line Loading @@ -13,66 +13,11 @@ from django.core.urlresolvers import set_script_prefix from django.utils import datastructures from django.utils.encoding import force_str, force_text, iri_to_uri logger = logging.getLogger('django.request') # For backwards compatibility -- lots of code uses this in the wild! from django.http.response import REASON_PHRASES as STATUS_CODE_TEXT logger = logging.getLogger('django.request') # See http://www.iana.org/assignments/http-status-codes STATUS_CODE_TEXT = { 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', 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', 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', } class LimitedStream(object): ''' Loading Loading @@ -254,11 +199,7 @@ class WSGIHandler(base.BaseHandler): response._handler_class = self.__class__ try: status_text = STATUS_CODE_TEXT[response.status_code] except KeyError: status_text = 'UNKNOWN STATUS CODE' status = '%s %s' % (response.status_code, status_text) status = '%s %s' % (response.status_code, response.reason_phrase) response_headers = [(str(k), str(v)) for k, v in response.items()] for c in response.cookies.values(): response_headers.append((str('Set-Cookie'), str(c.output(header='')))) Loading
django/http/response.py +67 −3 Original line number Diff line number Diff line Loading @@ -20,6 +20,65 @@ from django.utils.http import cookie_date from django.utils.six.moves import map # 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', 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', 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', } class BadHeaderError(ValueError): pass Loading @@ -33,8 +92,9 @@ class HttpResponseBase(six.Iterator): """ status_code = 200 reason_phrase = None # Use default reason phrase for status code. def __init__(self, content_type=None, status=None, mimetype=None): def __init__(self, content_type=None, status=None, reason=None, mimetype=None): # _headers is a mapping of the lower-case name to the original case of # the header (required for working with legacy systems) and the header # value. Both the name of the header and its value are ASCII strings. Loading @@ -53,9 +113,13 @@ class HttpResponseBase(six.Iterator): content_type = "%s; charset=%s" % (settings.DEFAULT_CONTENT_TYPE, self._charset) self.cookies = SimpleCookie() if status: if status is not None: self.status_code = status 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['Content-Type'] = content_type def serialize_headers(self): Loading
docs/ref/request-response.txt +21 −6 Original line number Diff line number Diff line Loading @@ -616,7 +616,13 @@ Attributes .. attribute:: HttpResponse.status_code The `HTTP Status code`_ for the response. The `HTTP status code`_ for the response. .. attribute:: HttpResponse.reason_phrase .. versionadded:: 1.6 The HTTP reason phrase for the response. .. attribute:: HttpResponse.streaming Loading @@ -628,7 +634,7 @@ Attributes Methods ------- .. method:: HttpResponse.__init__(content='', content_type=None, status=200) .. method:: HttpResponse.__init__(content='', content_type=None, status=200, reason=None) Instantiates an ``HttpResponse`` object with the given page content and content type. Loading @@ -646,8 +652,12 @@ Methods Historically, this parameter was called ``mimetype`` (now deprecated). ``status`` is the `HTTP Status code`_ for the response. ``status`` is the `HTTP status code`_ for the response. .. versionadded:: 1.6 ``reason`` is the HTTP response phrase. If not provided, a default phrase will be used. .. method:: HttpResponse.__setitem__(header, value) Loading Loading @@ -727,8 +737,7 @@ Methods This method makes an :class:`HttpResponse` instance a file-like object. .. _HTTP Status code: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10 .. _HTTP status code: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10 .. _ref-httpresponse-subclasses: Loading Loading @@ -851,7 +860,13 @@ Attributes .. attribute:: HttpResponse.status_code The `HTTP Status code`_ for the response. The `HTTP status code`_ for the response. .. attribute:: HttpResponse.reason_phrase .. versionadded:: 1.6 The HTTP reason phrase for the response. .. attribute:: HttpResponse.streaming Loading
docs/releases/1.6.txt +2 −0 Original line number Diff line number Diff line Loading @@ -241,6 +241,8 @@ Minor features * The ``choices`` argument to model fields now accepts an iterable of iterables instead of requiring an iterable of lists or tuples. * The reason phrase can be customized in HTTP responses. Backwards incompatible changes in 1.6 ===================================== Loading