summaryrefslogtreecommitdiff
path: root/django/http
diff options
context:
space:
mode:
authorUnai Zalakain <unai@gisa-elkartea.org>2013-11-16 18:54:12 +0100
committerTim Graham <timograham@gmail.com>2014-08-19 17:34:38 -0400
commit5f2542f12a90cfcfb7be776424ef2f7b200df006 (patch)
tree74e78ce1ed7c67e1eb009fcdf8de8e9596361537 /django/http
parent9d6551204eff9d1ab70b67578f99630716df7490 (diff)
Fixed #10190 -- Made HttpResponse charset customizable.
Thanks to Simon Charette, Aymeric Augustin, and Tim Graham for reviews and contributions.
Diffstat (limited to 'django/http')
-rw-r--r--django/http/response.py33
1 files changed, 26 insertions, 7 deletions
diff --git a/django/http/response.py b/django/http/response.py
index 866b3480e7..0cc14d1346 100644
--- a/django/http/response.py
+++ b/django/http/response.py
@@ -2,6 +2,7 @@ from __future__ import unicode_literals
import datetime
import json
+import re
import sys
import time
from email.header import Header
@@ -83,6 +84,9 @@ REASON_PHRASES = {
}
+_charset_from_content_type_re = re.compile(r';\s*charset=(?P<charset>[^\s;]+)', re.I)
+
+
class BadHeaderError(ValueError):
pass
@@ -98,19 +102,15 @@ 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, reason=None):
+ def __init__(self, content_type=None, status=None, reason=None, charset=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.
self._headers = {}
- self._charset = settings.DEFAULT_CHARSET
self._closable_objects = []
# This parameter is set by the handler. It's necessary to preserve the
# historical behavior of request_finished.
self._handler_class = None
- if not content_type:
- content_type = "%s; charset=%s" % (settings.DEFAULT_CONTENT_TYPE,
- self._charset)
self.cookies = SimpleCookie()
if status is not None:
self.status_code = status
@@ -119,8 +119,27 @@ class HttpResponseBase(six.Iterator):
elif self.reason_phrase is None:
self.reason_phrase = REASON_PHRASES.get(self.status_code,
'UNKNOWN STATUS CODE')
+ self._charset = charset
+ if content_type is None:
+ content_type = '%s; charset=%s' % (settings.DEFAULT_CONTENT_TYPE,
+ self.charset)
self['Content-Type'] = content_type
+ @property
+ def charset(self):
+ if self._charset is not None:
+ return self._charset
+ content_type = self.get('Content-Type', '')
+ matched = _charset_from_content_type_re.search(content_type)
+ if matched:
+ # Extract the charset and strip its double quotes
+ return matched.group('charset').replace('"', '')
+ return settings.DEFAULT_CHARSET
+
+ @charset.setter
+ def charset(self, value):
+ self._charset = value
+
def serialize_headers(self):
"""HTTP headers as a bytestring."""
def to_bytes(val, encoding):
@@ -278,10 +297,10 @@ class HttpResponseBase(six.Iterator):
if isinstance(value, bytes):
return bytes(value)
if isinstance(value, six.text_type):
- return bytes(value.encode(self._charset))
+ return bytes(value.encode(self.charset))
# Handle non-string types (#16494)
- return force_bytes(value, self._charset)
+ return force_bytes(value, self.charset)
# These methods partially implement the file-like object interface.
# See http://docs.python.org/lib/bltin-file-objects.html