| 1 | diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py
|
|---|
| 2 | index 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
|
|---|
| 52 | diff --git a/tests/regressiontests/requests/tests.py b/tests/regressiontests/requests/tests.py
|
|---|
| 53 | index 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 |
|
|---|