Skip to content

Commit

Permalink
Fixed #10571 -- Ensured that unicode POST data is correctly encoded b…
Browse files Browse the repository at this point in the history
…y the test client. Thanks to Rick Wagner for his help identifying and fixing this problem.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@10513 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
freakboy3742 committed Apr 11, 2009
1 parent 8fecf36 commit 8dc73e8
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 2 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Expand Up @@ -436,6 +436,7 @@ answer newbie questions, and generally made Django that much better:
Vlado <vlado@labath.org>
Milton Waddams
Chris Wagner <cw264701@ohio.edu>
Rick Wagner <rwagner@physics.ucsd.edu>
wam-djangobug@wamber.net
Wang Chun <wangchun@exoweb.net>
Filip Wasilewski <filip.wasilewski@gmail.com>
Expand Down
11 changes: 9 additions & 2 deletions django/test/client.py
Expand Up @@ -2,6 +2,7 @@
from urlparse import urlparse, urlunparse, urlsplit
import sys
import os
import re
try:
from cStringIO import StringIO
except ImportError:
Expand All @@ -25,7 +26,7 @@

BOUNDARY = 'BoUnDaRyStRiNg'
MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY

CONTENT_TYPE_RE = re.compile('.*; charset=([\w\d-]+);?')

class FakePayload(object):
"""
Expand Down Expand Up @@ -290,7 +291,13 @@ def post(self, path, data={}, content_type=MULTIPART_CONTENT,
if content_type is MULTIPART_CONTENT:
post_data = encode_multipart(BOUNDARY, data)
else:
post_data = data
# Encode the content so that the byte representation is correct.
match = CONTENT_TYPE_RE.match(content_type)
if match:
charset = match.group(1)
else:
charset = settings.DEFAULT_CHARSET
post_data = smart_str(data, encoding=charset)

parsed = urlparse(path)
r = {
Expand Down
33 changes: 33 additions & 0 deletions tests/regressiontests/test_client_regress/models.py
Expand Up @@ -624,3 +624,36 @@ def test_post_like_requests(self):
self.assertEqual(response.context['post-bar'], 'bang')
self.assertEqual(response.context['request-foo'], 'whiz')
self.assertEqual(response.context['request-bar'], 'bang')

class UnicodePayloadTests(TestCase):
def test_simple_unicode_payload(self):
"A simple ASCII-only unicode JSON document can be POSTed"
# Regression test for #10571
json = u'{"english": "mountain pass"}'
response = self.client.post("/test_client_regress/parse_unicode_json/", json,
content_type="application/json")
self.assertEqual(response.content, json)

def test_unicode_payload_utf8(self):
"A non-ASCII unicode data encoded as UTF-8 can be POSTed"
# Regression test for #10571
json = u'{"dog": "собака"}'
response = self.client.post("/test_client_regress/parse_unicode_json/", json,
content_type="application/json; charset=utf-8")
self.assertEqual(response.content, json.encode('utf-8'))

def test_unicode_payload_utf16(self):
"A non-ASCII unicode data encoded as UTF-16 can be POSTed"
# Regression test for #10571
json = u'{"dog": "собака"}'
response = self.client.post("/test_client_regress/parse_unicode_json/", json,
content_type="application/json; charset=utf-16")
self.assertEqual(response.content, json.encode('utf-16'))

def test_unicode_payload_non_utf(self):
"A non-ASCII unicode data as a non-UTF based encoding can be POSTed"
#Regression test for #10571
json = u'{"dog": "собака"}'
response = self.client.post("/test_client_regress/parse_unicode_json/", json,
content_type="application/json; charset=koi8-r")
self.assertEqual(response.content, json.encode('koi8-r'))
1 change: 1 addition & 0 deletions tests/regressiontests/test_client_regress/urls.py
Expand Up @@ -23,4 +23,5 @@
(r'^check_session/$', views.check_session_view),
(r'^request_methods/$', views.request_methods_view),
(r'^check_unicode/$', views.return_unicode),
(r'^parse_unicode_json/$', views.return_json_file),
)
23 changes: 23 additions & 0 deletions tests/regressiontests/test_client_regress/views.py
@@ -1,7 +1,12 @@
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse, HttpResponseRedirect
from django.core.exceptions import SuspiciousOperation
from django.shortcuts import render_to_response
from django.utils import simplejson
from django.utils.encoding import smart_str
from django.core.serializers.json import DjangoJSONEncoder
from django.test.client import CONTENT_TYPE_RE

def no_template_view(request):
"A simple view that expects a GET request, and returns a rendered template"
Expand Down Expand Up @@ -63,3 +68,21 @@ def request_methods_view(request):

def return_unicode(request):
return render_to_response('unicode.html')

def return_json_file(request):
"A view that parses and returns a JSON string as a file."
match = CONTENT_TYPE_RE.match(request.META['CONTENT_TYPE'])
if match:
charset = match.group(1)
else:
charset = settings.DEFAULT_CHARSET

# This just checks that the uploaded data is JSON
obj_dict = simplejson.loads(request.raw_post_data.decode(charset))
obj_json = simplejson.dumps(obj_dict, encoding=charset,
cls=DjangoJSONEncoder,
ensure_ascii=False)
response = HttpResponse(smart_str(obj_json, encoding=charset), status=200,
mimetype='application/json; charset=' + charset)
response['Content-Disposition'] = 'attachment; filename=testfile.json'
return response

0 comments on commit 8dc73e8

Please sign in to comment.