From 29592eef19abf8e58e4923d29bfba4fcbd085384 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Wed, 8 Mar 2017 20:07:09 +0100 Subject: [PATCH] Decoupled test client encoding tests from JSON handling Using JSON as non-UTF-8 content is controversial, and the RFC 7159 discourages it. Thanks Tim Graham for the review. --- tests/test_client_regress/tests.py | 47 ++++++++++++++---------------- tests/test_client_regress/urls.py | 2 +- tests/test_client_regress/views.py | 13 ++------- 3 files changed, 26 insertions(+), 36 deletions(-) diff --git a/tests/test_client_regress/tests.py b/tests/test_client_regress/tests.py index c9dffdb35d..b35bad43a2 100644 --- a/tests/test_client_regress/tests.py +++ b/tests/test_client_regress/tests.py @@ -1268,35 +1268,32 @@ class QueryStringTests(SimpleTestCase): @override_settings(ROOT_URLCONF='test_client_regress.urls') -class UnicodePayloadTests(SimpleTestCase): +class PayloadEncodingTests(SimpleTestCase): + """Regression tests for #10571.""" - def test_simple_unicode_payload(self): - "A simple ASCII-only JSON document can be POSTed" - # Regression test for #10571 - json_str = '{"english": "mountain pass"}' - response = self.client.post("/parse_unicode_json/", json_str, content_type="application/json") - self.assertEqual(response.content, json_str.encode()) + def test_simple_payload(self): + """A simple ASCII-only text can be POSTed.""" + text = 'English: mountain pass' + response = self.client.post('/parse_encoded_text/', text, content_type='text/plain') + self.assertEqual(response.content, text.encode()) - def test_unicode_payload_utf8(self): - "A non-ASCII unicode data encoded as UTF-8 can be POSTed" - # Regression test for #10571 - json_str = '{"dog": "собака"}' - response = self.client.post("/parse_unicode_json/", json_str, content_type="application/json; charset=utf-8") - self.assertEqual(response.content, json_str.encode()) + def test_utf8_payload(self): + """Non-ASCII data encoded as UTF-8 can be POSTed.""" + text = 'dog: собака' + response = self.client.post('/parse_encoded_text/', text, content_type='text/plain; charset=utf-8') + self.assertEqual(response.content, text.encode()) - def test_unicode_payload_utf16(self): - "A non-ASCII unicode data encoded as UTF-16 can be POSTed" - # Regression test for #10571 - json_str = '{"dog": "собака"}' - response = self.client.post("/parse_unicode_json/", json_str, content_type="application/json; charset=utf-16") - self.assertEqual(response.content, json_str.encode('utf-16')) + def test_utf16_payload(self): + """Non-ASCII data encoded as UTF-16 can be POSTed.""" + text = 'dog: собака' + response = self.client.post('/parse_encoded_text/', text, content_type='text/plain; charset=utf-16') + self.assertEqual(response.content, text.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_str = '{"dog": "собака"}' - response = self.client.post("/parse_unicode_json/", json_str, content_type="application/json; charset=koi8-r") - self.assertEqual(response.content, json_str.encode('koi8-r')) + def test_non_utf_payload(self): + """Non-ASCII data as a non-UTF based encoding can be POSTed.""" + text = 'dog: собака' + response = self.client.post('/parse_encoded_text/', text, content_type='text/plain; charset=koi8-r') + self.assertEqual(response.content, text.encode('koi8-r')) class DummyFile: diff --git a/tests/test_client_regress/urls.py b/tests/test_client_regress/urls.py index 9821ea910d..eeec49b8ce 100644 --- a/tests/test_client_regress/urls.py +++ b/tests/test_client_regress/urls.py @@ -31,7 +31,7 @@ urlpatterns = [ url(r'^check_unicode/$', views.return_unicode), url(r'^check_binary/$', views.return_undecodable_binary), url(r'^json_response/$', views.return_json_response), - url(r'^parse_unicode_json/$', views.return_json_file), + url(r'^parse_encoded_text/$', views.return_text_file), url(r'^check_headers/$', views.check_headers), url(r'^check_headers_redirect/$', RedirectView.as_view(url='/check_headers/')), url(r'^body/$', views.body), diff --git a/tests/test_client_regress/views.py b/tests/test_client_regress/views.py index 854cdc3bc0..5e4c9968fd 100644 --- a/tests/test_client_regress/views.py +++ b/tests/test_client_regress/views.py @@ -1,9 +1,7 @@ -import json from urllib.parse import urlencode from django.conf import settings from django.contrib.auth.decorators import login_required -from django.core.serializers.json import DjangoJSONEncoder from django.http import HttpResponse, HttpResponseRedirect, JsonResponse from django.shortcuts import render from django.template.loader import render_to_string @@ -111,20 +109,15 @@ def return_json_response(request): return JsonResponse({'key': 'value'}, **kwargs) -def return_json_file(request): - "A view that parses and returns a JSON string as a file." +def return_text_file(request): + "A view that parses and returns text 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 = json.loads(request.body.decode(charset)) - obj_json = json.dumps(obj_dict, cls=DjangoJSONEncoder, ensure_ascii=False) - response = HttpResponse(obj_json.encode(charset), status=200, - content_type='application/json; charset=%s' % charset) - response['Content-Disposition'] = 'attachment; filename=testfile.json' + response = HttpResponse(request.body, status=200, content_type='text/plain; charset=%s' % charset) return response