Ticket #19468: 19468-2.diff

File 19468-2.diff, 3.9 KB (added by Claude Paroz, 12 years ago)
Line 
1diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py
2index 4c07105..a148751 100644
3--- a/django/core/handlers/wsgi.py
4+++ b/django/core/handlers/wsgi.py
5@@ -7,11 +7,13 @@ from io import BytesIO
6 from threading import Lock
7
8 from django import http
9+from django.conf import settings
10 from django.core import signals
11 from django.core.handlers import base
12 from django.core.urlresolvers import set_script_prefix
13 from django.utils import datastructures
14 from django.utils.encoding import force_str, force_text, iri_to_uri
15+from django.utils import six
16
17 logger = logging.getLogger('django.request')
18
19@@ -125,10 +127,31 @@ class LimitedStream(object):
20 return line
21
22
23+def fix_path_info(path):
24+ """
25+ On Python 3, wsgiref.WSGIRequestHandler is unconditionally decoding the
26+ request path with 'iso-8859-1' encoding. We have to fix this.
27+ See https://code.djangoproject.com/ticket/19468 and
28+ http://bugs.python.org/issue16679
29+ """
30+ path_enc = path.encode('iso-8859-1')
31+ try:
32+ return path_enc.decode('utf-8')
33+ except UnicodeDecodeError:
34+ if settings.DEFAULT_CHARSET not in ('utf-8', 'iso-8859-1', 'latin-1'):
35+ try:
36+ return path_enc.decode(settings.DEFAULT_CHARSET)
37+ except:
38+ pass
39+ return path
40+
41 class WSGIRequest(http.HttpRequest):
42 def __init__(self, environ):
43 script_name = base.get_script_name(environ)
44- path_info = force_text(environ.get('PATH_INFO', '/'))
45+ if six.PY3:
46+ path_info = fix_path_info(environ.get('PATH_INFO', '/'))
47+ else:
48+ path_info = force_text(environ.get('PATH_INFO', '/'))
49 if not path_info or path_info == script_name:
50 # Sometimes PATH_INFO exists, but is empty (e.g. accessing
51 # the SCRIPT_NAME URL without a trailing slash). We really need to
52diff --git a/tests/regressiontests/requests/tests.py b/tests/regressiontests/requests/tests.py
53index adf824d..432c7d5 100644
54--- a/tests/regressiontests/requests/tests.py
55+++ b/tests/regressiontests/requests/tests.py
56@@ -11,6 +11,7 @@ from django.core.handlers.wsgi import WSGIRequest, LimitedStream
57 from django.http import HttpRequest, HttpResponse, parse_cookie, build_request_repr, UnreadablePostError
58 from django.test.client import FakePayload
59 from django.test.utils import override_settings, str_prefix
60+from django.utils import six
61 from django.utils import unittest
62 from django.utils.http import cookie_date, urlencode
63 from django.utils.timezone import utc
64@@ -57,6 +58,19 @@ class RequestsTests(unittest.TestCase):
65 self.assertEqual(build_request_repr(request, path_override='/otherpath/', GET_override={'a': 'b'}, POST_override={'c': 'd'}, COOKIES_override={'e': 'f'}, META_override={'g': 'h'}),
66 str_prefix("<WSGIRequest\npath:/otherpath/,\nGET:{%(_)s'a': %(_)s'b'},\nPOST:{%(_)s'c': %(_)s'd'},\nCOOKIES:{%(_)s'e': %(_)s'f'},\nMETA:{%(_)s'g': %(_)s'h'}>"))
67
68+ @unittest.skipUnless(six.PY3, "PATH_INFO decoding only happens on Python 3")
69+ def test_wsgirequest_path_info(self):
70+ """Testing fix for #19468"""
71+ request = WSGIRequest({'PATH_INFO': '/سلام
72/', 'REQUEST_METHOD': 'get', 'wsgi.input': BytesIO(b'')})
73+ self.assertEqual(request.path, "/سلام/")
74+ # Test path encoded with iso-8859-1
75+ request = WSGIRequest({'PATH_INFO': '/café/', 'REQUEST_METHOD': 'get', 'wsgi.input': BytesIO(b'')})
76+ self.assertEqual(request.path, "/café/")
77+ # Test when DEFAULT_CHARSET is customized
78+ with override_settings(DEFAULT_CHARSET='windows-1252'):
79+ request = WSGIRequest({'PATH_INFO': '/400\x80/', 'REQUEST_METHOD': 'get', 'wsgi.input': BytesIO(b'')})
80+ self.assertEqual(request.path, "/400€/")
81+
82 def test_parse_cookie(self):
83 self.assertEqual(parse_cookie('invalid@key=true'), {})
84
Back to Top