mirror of
https://github.com/django/django.git
synced 2025-07-04 09:49:12 +00:00
[soc2009/http-wsgi-improvements] Change HttpResponse.status_code to a property, additional test coverage. Refs #10190.
Improve charset coverage. Change HttpResponse.status_code to property, which checks for a 406 situation. This also required changes to all HttpResponse subclasses, so that their default status_code is set by _status_code, now. Passes regression test suite, except ones related to sendfile. git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/http-wsgi-improvements@11199 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
4d46aed514
commit
8d979aecbe
@ -13,7 +13,7 @@ except ImportError:
|
|||||||
from django.utils.datastructures import MultiValueDict, ImmutableList
|
from django.utils.datastructures import MultiValueDict, ImmutableList
|
||||||
from django.utils.encoding import smart_str, iri_to_uri, force_unicode
|
from django.utils.encoding import smart_str, iri_to_uri, force_unicode
|
||||||
from django.http.multipartparser import MultiPartParser
|
from django.http.multipartparser import MultiPartParser
|
||||||
from django.http.charsets import determine_charset, get_codec
|
from django.http.charsets import get_response_encoding, get_codec
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.files import uploadhandler
|
from django.core.files import uploadhandler
|
||||||
from utils import *
|
from utils import *
|
||||||
@ -270,24 +270,21 @@ class BadHeaderError(ValueError):
|
|||||||
class HttpResponse(object):
|
class HttpResponse(object):
|
||||||
"""A basic HTTP response, with content and dictionary-accessed headers."""
|
"""A basic HTTP response, with content and dictionary-accessed headers."""
|
||||||
|
|
||||||
status_code = 200
|
_status_code = 200
|
||||||
|
_codec = None
|
||||||
|
_charset = settings.DEFAULT_CHARSET
|
||||||
|
|
||||||
def __init__(self, content='', mimetype=None, status=None,
|
def __init__(self, content='', mimetype=None, status=None,
|
||||||
content_type=None, request=None):
|
content_type=None, request=None):
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
self._charset = settings.DEFAULT_CHARSET
|
|
||||||
self._codec = None
|
|
||||||
accept_charset = None
|
accept_charset = None
|
||||||
if mimetype:
|
if mimetype:
|
||||||
content_type = mimetype # Mimetype is an alias for content-type
|
content_type = mimetype # Mimetype arg is an alias for content-type
|
||||||
if request:
|
if request:
|
||||||
accept_charset = request.META.get("ACCEPT_CHARSET")
|
accept_charset = request.META.get("ACCEPT_CHARSET")
|
||||||
if accept_charset or content_type:
|
if accept_charset or content_type:
|
||||||
charset, codec = determine_charset(content_type, accept_charset)
|
encoding = get_response_encoding(content_type, accept_charset)
|
||||||
if charset:
|
(self._charset, self._codec) = encoding
|
||||||
self._charset = charset
|
|
||||||
if codec:
|
|
||||||
self._codec = codec
|
|
||||||
if not content_type:
|
if not content_type:
|
||||||
content_type = "%s; charset=%s" % (settings.DEFAULT_CONTENT_TYPE,
|
content_type = "%s; charset=%s" % (settings.DEFAULT_CONTENT_TYPE,
|
||||||
self._charset)
|
self._charset)
|
||||||
@ -370,12 +367,27 @@ class HttpResponse(object):
|
|||||||
self.set_cookie(key, max_age=0, path=path, domain=domain,
|
self.set_cookie(key, max_age=0, path=path, domain=domain,
|
||||||
expires='Thu, 01-Jan-1970 00:00:00 GMT')
|
expires='Thu, 01-Jan-1970 00:00:00 GMT')
|
||||||
|
|
||||||
|
def _get_status_code(self):
|
||||||
|
if not self._valid_codec():
|
||||||
|
self._status_code = 406
|
||||||
|
self._container = ['']
|
||||||
|
return self._status_code
|
||||||
|
|
||||||
|
def _set_status_code(self, value):
|
||||||
|
self._status_code = value
|
||||||
|
|
||||||
|
status_code = property(_get_status_code, _set_status_code)
|
||||||
|
|
||||||
|
def _valid_codec(self):
|
||||||
|
if not self._codec:
|
||||||
|
self._codec = get_codec(self._charset)
|
||||||
|
if not self._codec:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def _get_content(self):
|
def _get_content(self):
|
||||||
if self.has_header('Content-Encoding'):
|
if self.has_header('Content-Encoding'):
|
||||||
return ''.join(self._container)
|
return ''.join(self._container)
|
||||||
|
|
||||||
if not self._codec:
|
|
||||||
self._codec = get_codec(self._charset)
|
|
||||||
return smart_str(''.join(self._container), self._codec.name)
|
return smart_str(''.join(self._container), self._codec.name)
|
||||||
|
|
||||||
def _set_content(self, value):
|
def _set_content(self, value):
|
||||||
@ -390,8 +402,6 @@ class HttpResponse(object):
|
|||||||
|
|
||||||
def next(self):
|
def next(self):
|
||||||
chunk = self._iterator.next()
|
chunk = self._iterator.next()
|
||||||
if not self._codec:
|
|
||||||
self._codec = get_codec(self._charset)
|
|
||||||
if isinstance(chunk, unicode):
|
if isinstance(chunk, unicode):
|
||||||
chunk = chunk.encode(self._codec.name)
|
chunk = chunk.encode(self._codec.name)
|
||||||
return str(chunk)
|
return str(chunk)
|
||||||
@ -432,57 +442,57 @@ class HttpResponseSendFile(HttpResponse):
|
|||||||
self[settings.HTTPRESPONSE_SENDFILE_HEADER] = path_to_file
|
self[settings.HTTPRESPONSE_SENDFILE_HEADER] = path_to_file
|
||||||
|
|
||||||
def _get_content(self):
|
def _get_content(self):
|
||||||
return open(self.sendfile_filename)
|
return open(self.sendfile_filename).read()
|
||||||
|
|
||||||
content = property(_get_content)
|
content = property(_get_content)
|
||||||
|
|
||||||
class HttpResponseRedirect(HttpResponse):
|
class HttpResponseRedirect(HttpResponse):
|
||||||
status_code = 302
|
_status_code = 302
|
||||||
|
|
||||||
def __init__(self, redirect_to):
|
def __init__(self, redirect_to):
|
||||||
HttpResponse.__init__(self)
|
HttpResponse.__init__(self)
|
||||||
self['Location'] = redirect_to
|
self['Location'] = redirect_to
|
||||||
|
|
||||||
class HttpResponsePermanentRedirect(HttpResponse):
|
class HttpResponsePermanentRedirect(HttpResponse):
|
||||||
status_code = 301
|
_status_code = 301
|
||||||
|
|
||||||
def __init__(self, redirect_to):
|
def __init__(self, redirect_to):
|
||||||
HttpResponse.__init__(self)
|
HttpResponse.__init__(self)
|
||||||
self['Location'] = redirect_to
|
self['Location'] = redirect_to
|
||||||
|
|
||||||
class HttpResponseNotModified(HttpResponse):
|
class HttpResponseNotModified(HttpResponse):
|
||||||
status_code = 304
|
_status_code = 304
|
||||||
|
|
||||||
class HttpResponseBadRequest(HttpResponse):
|
class HttpResponseBadRequest(HttpResponse):
|
||||||
status_code = 400
|
_status_code = 400
|
||||||
|
|
||||||
class HttpResponseNotFound(HttpResponse):
|
class HttpResponseNotFound(HttpResponse):
|
||||||
status_code = 404
|
_status_code = 404
|
||||||
|
|
||||||
class HttpResponseForbidden(HttpResponse):
|
class HttpResponseForbidden(HttpResponse):
|
||||||
status_code = 403
|
_status_code = 403
|
||||||
|
|
||||||
class HttpResponseNotAllowed(HttpResponse):
|
class HttpResponseNotAllowed(HttpResponse):
|
||||||
status_code = 405
|
_status_code = 405
|
||||||
|
|
||||||
def __init__(self, permitted_methods):
|
def __init__(self, permitted_methods):
|
||||||
HttpResponse.__init__(self)
|
HttpResponse.__init__(self)
|
||||||
self['Allow'] = ', '.join(permitted_methods)
|
self['Allow'] = ', '.join(permitted_methods)
|
||||||
|
|
||||||
class HttpResponseNotAcceptable(HttpResponse):
|
class HttpResponseNotAcceptable(HttpResponse):
|
||||||
status_code = 406
|
_status_code = 406
|
||||||
|
|
||||||
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
||||||
# if we want to make this more verbose (compliant, actually)
|
# if we want to make this more verbose (compliant, actually)
|
||||||
|
|
||||||
class HttpResponseGone(HttpResponse):
|
class HttpResponseGone(HttpResponse):
|
||||||
status_code = 410
|
_status_code = 410
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
HttpResponse.__init__(self, *args, **kwargs)
|
HttpResponse.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
class HttpResponseServerError(HttpResponse):
|
class HttpResponseServerError(HttpResponse):
|
||||||
status_code = 500
|
_status_code = 500
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
HttpResponse.__init__(self, *args, **kwargs)
|
HttpResponse.__init__(self, *args, **kwargs)
|
||||||
|
@ -235,16 +235,14 @@ def get_codec(charset):
|
|||||||
|
|
||||||
CODEC_CHARSETS above has the codecs that correspond to character sets.
|
CODEC_CHARSETS above has the codecs that correspond to character sets.
|
||||||
"""
|
"""
|
||||||
try:
|
codec = None
|
||||||
codec_name = CHARSET_CODECS[charset.strip().lower()]
|
if charset:
|
||||||
codec = codecs.lookup(codec_name)
|
try:
|
||||||
except KeyError:
|
codec_name = CHARSET_CODECS[charset.strip().lower()]
|
||||||
#print "The charset %s is not supported by Django." % charset
|
codec = codecs.lookup(codec_name)
|
||||||
codec = None
|
except LookupError:
|
||||||
except LookupError:
|
# The encoding is not supported in this version of Python.
|
||||||
#print "The encoding '%s' is not supported in this version of Python." % codec_name
|
pass
|
||||||
codec = None
|
|
||||||
|
|
||||||
return codec
|
return codec
|
||||||
|
|
||||||
# Returns the key for the maximum value in a dictionary
|
# Returns the key for the maximum value in a dictionary
|
||||||
@ -252,7 +250,7 @@ max_dict_key = lambda l:sorted(l.iteritems(), key=itemgetter(1), reverse=True)[0
|
|||||||
|
|
||||||
CONTENT_TYPE_RE = re.compile('.*; charset=([\w\d-]+);?')
|
CONTENT_TYPE_RE = re.compile('.*; charset=([\w\d-]+);?')
|
||||||
ACCEPT_CHARSET_RE = re.compile('(?P<charset>([\w\d-]+)|(\*))(;q=(?P<q>[01](\.\d{1,3})?))?,?')
|
ACCEPT_CHARSET_RE = re.compile('(?P<charset>([\w\d-]+)|(\*))(;q=(?P<q>[01](\.\d{1,3})?))?,?')
|
||||||
def determine_charset(content_type, accept_charset_header):
|
def get_response_encoding(content_type, accept_charset_header):
|
||||||
"""
|
"""
|
||||||
Searches request headers from clients and mimetype settings (which may be set
|
Searches request headers from clients and mimetype settings (which may be set
|
||||||
by users) for indicators of which charset and encoding the response should use.
|
by users) for indicators of which charset and encoding the response should use.
|
||||||
@ -268,56 +266,54 @@ def determine_charset(content_type, accept_charset_header):
|
|||||||
406 error
|
406 error
|
||||||
|
|
||||||
"""
|
"""
|
||||||
codec = None
|
used_content_type = False
|
||||||
charset = None
|
charset = None
|
||||||
# Attempt to get the codec from a content-type, and verify that the charset is valid.
|
codec = None
|
||||||
|
# Try to get the codec from a content-type, verify that the charset is valid.
|
||||||
if content_type:
|
if content_type:
|
||||||
match = CONTENT_TYPE_RE.match(content_type)
|
match = CONTENT_TYPE_RE.match(content_type)
|
||||||
if match:
|
if match:
|
||||||
charset = match.group(1)
|
charset = match.group(1)
|
||||||
codec = get_codec(charset)
|
codec = get_codec(charset)
|
||||||
if not codec: # Unsupported charset
|
if not codec: # Unsupported charset
|
||||||
# we should throw an exception here
|
raise Exception("Unsupported charset in Content-Type header.")
|
||||||
# print "No CODEC ON MIMETYPE"
|
|
||||||
pass
|
|
||||||
# If we don't match a content-type header WITH charset, we give the default
|
|
||||||
else:
|
else:
|
||||||
charset = settings.DEFAULT_CHARSET
|
charset = settings.DEFAULT_CHARSET
|
||||||
codec = get_codec(settings.DEFAULT_CHARSET)
|
used_content_type = True
|
||||||
|
|
||||||
# Handle Accept-Charset (which we only do if we do not deal with content_type).
|
# Handle Accept-Charset (only if we have not gotten one with content_type).
|
||||||
else:
|
if not used_content_type:
|
||||||
if accept_charset_header:
|
if not accept_charset_header: # No information to find a charset with.
|
||||||
# Get list of matches for Accepted-Charsets.
|
return None, None
|
||||||
# [{ charset : q }, { charset : q }]
|
# Get list of matches for Accepted-Charsets.
|
||||||
match_iterator = ACCEPT_CHARSET_RE.finditer(accept_charset_header)
|
# [{ charset : q }, { charset : q }]
|
||||||
accept_charset = [m.groupdict() for m in match_iterator]
|
match_iterator = ACCEPT_CHARSET_RE.finditer(accept_charset_header)
|
||||||
else:
|
accept_charset = [m.groupdict() for m in match_iterator]
|
||||||
accept_charset = [] # use settings.DEFAULT_CHARSET
|
|
||||||
charset = settings.DEFAULT_CHARSET
|
|
||||||
|
|
||||||
# Remove charsets we cannot encode and whose q values are 0
|
# Remove charsets we cannot encode and whose q values are 0
|
||||||
charsets = _process_accept_charset(accept_charset)
|
charsets = _process_accept_charset(accept_charset)
|
||||||
|
|
||||||
# If we did not get a charset from the content type, we get it from accept_charset.
|
# Establish the prioritized charsets (ones we know about beforehand)
|
||||||
if not charset:
|
default_charset = settings.DEFAULT_CHARSET
|
||||||
default_charset = settings.DEFAULT_CHARSET
|
fallback_charset = "ISO-8859-1"
|
||||||
fallback_charset = "ISO-8859-1"
|
|
||||||
# Prefer default_charset if its q value is 1 or we have no valid acceptable charsets.
|
|
||||||
max_q_charset = max_dict_key(charsets)
|
|
||||||
max_q_value = charsets[max_q_charset]
|
|
||||||
if max_q_value == 0 and fallback_charset not in charsets:
|
|
||||||
charset = fallback_charset
|
|
||||||
elif charsets[default_charset] == 1 or charsets[default_charset] == max_q_value:
|
|
||||||
charset = default_charset
|
|
||||||
# Get the highest valued acceptable charset (if we aren't going to the fallback
|
|
||||||
# or defaulting)
|
|
||||||
else:
|
|
||||||
charset = max_q_charset
|
|
||||||
|
|
||||||
codec = get_codec(charset)
|
# Prefer default_charset if its q value is 1 or we have no valid acceptable charsets.
|
||||||
|
max_q_charset = max_dict_key(charsets)
|
||||||
|
max_q_value = charsets[max_q_charset]
|
||||||
|
if max_q_value == 0:
|
||||||
|
if fallback_charset not in charsets or charsets[fallback_charset] > 0:
|
||||||
|
charset = fallback_charset
|
||||||
|
elif charsets[default_charset] == 1 or charsets[default_charset] == max_q_value:
|
||||||
|
charset = default_charset
|
||||||
|
# Get the highest valued acceptable charset (if we aren't going to the fallback
|
||||||
|
# or defaulting)
|
||||||
|
else:
|
||||||
|
charset = max_q_charset
|
||||||
|
|
||||||
|
codec = get_codec(charset)
|
||||||
# We may reach here with no codec or no charset. We will change the status
|
# We may reach here with no codec or no charset. We will change the status
|
||||||
# code in the HttpResponse.
|
# code in the HttpResponse.
|
||||||
|
#print charset, codec
|
||||||
return charset, codec
|
return charset, codec
|
||||||
|
|
||||||
# NOTE -- make sure we are not duping the processing of q values
|
# NOTE -- make sure we are not duping the processing of q values
|
||||||
|
@ -2,12 +2,12 @@ import re
|
|||||||
|
|
||||||
from django.test import Client, TestCase
|
from django.test import Client, TestCase
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.http.charsets import determine_charset, get_codec
|
from django.http.charsets import get_response_encoding, get_codec
|
||||||
|
|
||||||
|
|
||||||
CONTENT_TYPE_RE = re.compile('.*; charset=([\w\d-]+);?')
|
CHARSET_RE = re.compile('.*; charset=([\w\d-]+);?')
|
||||||
def get_charset(response):
|
def get_charset(response):
|
||||||
match = CONTENT_TYPE_RE.match(response.get("content-type",""))
|
match = CHARSET_RE.match(response.get("content-type",""))
|
||||||
if match:
|
if match:
|
||||||
charset = match.group(1)
|
charset = match.group(1)
|
||||||
else:
|
else:
|
||||||
@ -18,7 +18,7 @@ class ClientTest(TestCase):
|
|||||||
urls = 'regressiontests.charsets.urls'
|
urls = 'regressiontests.charsets.urls'
|
||||||
|
|
||||||
def test_good_accept_charset(self):
|
def test_good_accept_charset(self):
|
||||||
"Use Accept-Charset"
|
"Use Accept-Charset, with a quality value that throws away default_charset"
|
||||||
# The data is ignored, but let's check it doesn't crash the system
|
# The data is ignored, but let's check it doesn't crash the system
|
||||||
# anyway.
|
# anyway.
|
||||||
|
|
||||||
@ -27,61 +27,67 @@ class ClientTest(TestCase):
|
|||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(get_charset(response), "ascii")
|
self.assertEqual(get_charset(response), "ascii")
|
||||||
|
|
||||||
def test_good_accept_charset2(self):
|
def test_quality_sorting_wildcard_wins(self):
|
||||||
# us is an alias for ascii
|
|
||||||
response = self.client.post('/accept_charset/', ACCEPT_CHARSET="us;q=0.8,*;q=0.9")
|
response = self.client.post('/accept_charset/', ACCEPT_CHARSET="us;q=0.8,*;q=0.9")
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(get_charset(response), settings.DEFAULT_CHARSET)
|
self.assertEqual(get_charset(response), settings.DEFAULT_CHARSET)
|
||||||
|
|
||||||
def test_good_accept_charset3(self):
|
def test_quality_sorting_wildcard_loses_alias_wins(self):
|
||||||
|
# us is an alias for ascii
|
||||||
response = self.client.post('/accept_charset/', ACCEPT_CHARSET="us;q=0.8,*;q=0.7")
|
response = self.client.post('/accept_charset/', ACCEPT_CHARSET="us;q=0.8,*;q=0.7")
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(get_charset(response), "us")
|
self.assertEqual(get_charset(response), "us")
|
||||||
|
|
||||||
def test_good_accept_charset4(self):
|
def test_quality_sorting(self):
|
||||||
response = self.client.post('/accept_charset/', ACCEPT_CHARSET="ascii;q=0.89,utf-8;q=.9")
|
response = self.client.post('/accept_charset/', ACCEPT_CHARSET="ascii;q=0.89,utf-8;q=.9")
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(get_charset(response), settings.DEFAULT_CHARSET)
|
self.assertEqual(get_charset(response), settings.DEFAULT_CHARSET)
|
||||||
|
|
||||||
def test_good_accept_charset5(self):
|
def test_fallback_charset(self):
|
||||||
response = self.client.post('/accept_charset/', ACCEPT_CHARSET="utf-8;q=0")
|
response = self.client.post('/accept_charset/', ACCEPT_CHARSET="utf-8;q=0")
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(get_charset(response), "ISO-8859-1")
|
self.assertEqual(get_charset(response), "ISO-8859-1")
|
||||||
|
|
||||||
def test_bad_accept_charset(self):
|
def test_bad_accept_charset(self):
|
||||||
"Do not use a malformed Accept-Charset"
|
"Do not use a charset that Python does not support"
|
||||||
# The data is ignored, but let's check it doesn't crash the system
|
|
||||||
# anyway.
|
|
||||||
|
|
||||||
response = self.client.post('/accept_charset/', ACCEPT_CHARSET="this_is_junk")
|
response = self.client.post('/accept_charset/', ACCEPT_CHARSET="Huttese")
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(get_charset(response), "utf-8")
|
self.assertEqual(get_charset(response), "utf-8")
|
||||||
|
|
||||||
|
def test_force_no_charset(self):
|
||||||
|
"If we have no accepted charsets that we have codecs for, 406"
|
||||||
|
response = self.client.post('/accept_charset/', ACCEPT_CHARSET="utf-8;q=0,*;q=0")
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 406)
|
||||||
|
|
||||||
def test_good_content_type(self):
|
def test_good_content_type(self):
|
||||||
"Use good content-type"
|
"Use good content-type"
|
||||||
# The data is ignored, but let's check it doesn't crash the system
|
|
||||||
# anyway.
|
|
||||||
|
|
||||||
response = self.client.post('/good_content_type/')
|
response = self.client.post('/good_content_type/')
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertEqual(get_charset(response), "us")
|
||||||
|
|
||||||
def test_bad_content_type(self):
|
def test_bad_content_type(self):
|
||||||
"Use bad content-type"
|
"Use bad content-type"
|
||||||
|
self.assertRaises(Exception, self.client.get, "/bad_content_type/")
|
||||||
response = self.client.post('/bad_content_type/')
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
self.assertEqual(get_codec(get_charset(response)), None)
|
|
||||||
|
|
||||||
def test_content_type_no_charset(self):
|
def test_content_type_no_charset(self):
|
||||||
response = self.client.post('/content_type_no_charset/')
|
response = self.client.post('/content_type_no_charset/')
|
||||||
self.assertEqual(get_charset(response), None)
|
self.assertEqual(get_charset(response), None)
|
||||||
|
|
||||||
def test_determine_charset(self):
|
def test_determine_charset(self):
|
||||||
content_type, codec = determine_charset("", "utf-8;q=0.8,*;q=0.9")
|
content_type, codec = get_response_encoding("", "utf-8;q=0.8,*;q=0.9")
|
||||||
self.assertEqual(codec, get_codec("ISO-8859-1"))
|
self.assertEqual(codec, get_codec("ISO-8859-1"))
|
||||||
|
|
||||||
|
def test_basic_response(self):
|
||||||
|
"Make sure a normal request gets the default charset, with a 200 response."
|
||||||
|
response = self.client.post('/basic_response/')
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertEqual(get_charset(response), settings.DEFAULT_CHARSET)
|
||||||
|
|
||||||
|
@ -19,4 +19,5 @@ urlpatterns = patterns('',
|
|||||||
(r'^good_content_type/', views.good_content_type),
|
(r'^good_content_type/', views.good_content_type),
|
||||||
(r'^bad_content_type/', views.bad_content_type),
|
(r'^bad_content_type/', views.bad_content_type),
|
||||||
(r'^content_type_no_charset/', views.content_type_no_charset),
|
(r'^content_type_no_charset/', views.content_type_no_charset),
|
||||||
|
(r'^basic_response/', views.basic_response),
|
||||||
)
|
)
|
||||||
|
@ -15,3 +15,6 @@ def content_type_no_charset(request):
|
|||||||
|
|
||||||
def encode_response(request):
|
def encode_response(request):
|
||||||
return HttpResponse(u"\ue863", content_type="text/html; charset=GBK")
|
return HttpResponse(u"\ue863", content_type="text/html; charset=GBK")
|
||||||
|
|
||||||
|
def basic_response(request):
|
||||||
|
return HttpResponse("ASCII.")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user