From 095eca8dd85cb27ed0b22829903df10f19cdab6c Mon Sep 17 00:00:00 2001 From: Aymeric Augustin Date: Sat, 3 Nov 2012 12:54:06 +0100 Subject: [PATCH] Fixed #19101 -- Decoding of non-ASCII POST data on Python 3. Thanks Claude Paroz. --- django/http/multipartparser.py | 2 +- django/http/request.py | 3 +++ tests/regressiontests/requests/tests.py | 12 +++++++++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/django/http/multipartparser.py b/django/http/multipartparser.py index 40aefd6e9d..5bcc874982 100644 --- a/django/http/multipartparser.py +++ b/django/http/multipartparser.py @@ -110,7 +110,7 @@ class MultiPartParser(object): # HTTP spec says that Content-Length >= 0 is valid # handling content-length == 0 before continuing if self._content_length == 0: - return QueryDict(MultiValueDict(), encoding=self._encoding), MultiValueDict() + return QueryDict('', encoding=self._encoding), MultiValueDict() # See if the handler will want to take care of the parsing. # This allows overriding everything if somebody wants it. diff --git a/django/http/request.py b/django/http/request.py index 96c7606c86..d3f0888d47 100644 --- a/django/http/request.py +++ b/django/http/request.py @@ -276,6 +276,9 @@ class QueryDict(MultiValueDict): encoding = settings.DEFAULT_CHARSET self.encoding = encoding if six.PY3: + if isinstance(query_string, bytes): + # query_string contains URL-encoded data, a subset of ASCII. + query_string = query_string.decode() for key, value in parse_qsl(query_string or '', keep_blank_values=True, encoding=encoding): diff --git a/tests/regressiontests/requests/tests.py b/tests/regressiontests/requests/tests.py index eaf25ea7a6..164c1082fe 100644 --- a/tests/regressiontests/requests/tests.py +++ b/tests/regressiontests/requests/tests.py @@ -12,7 +12,7 @@ from django.http import HttpRequest, HttpResponse, parse_cookie, build_request_r from django.test.client import FakePayload from django.test.utils import override_settings, str_prefix from django.utils import unittest -from django.utils.http import cookie_date +from django.utils.http import cookie_date, urlencode from django.utils.timezone import utc @@ -353,6 +353,16 @@ class RequestsTests(unittest.TestCase): self.assertRaises(Exception, lambda: request.body) self.assertEqual(request.POST, {}) + def test_non_ascii_POST(self): + payload = FakePayload(urlencode({'key': 'España'})) + request = WSGIRequest({ + 'REQUEST_METHOD': 'POST', + 'CONTENT_LENGTH': len(payload), + 'CONTENT_TYPE': 'application/x-www-form-urlencoded', + 'wsgi.input': payload, + }) + self.assertEqual(request.POST, {'key': ['España']}) + def test_alternate_charset_POST(self): """ Test a POST with non-utf-8 payload encoding.