Loading django/contrib/staticfiles/handlers.py +2 −1 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ except ImportError: # Python 2 from urlparse import urlparse from django.conf import settings from django.core.handlers.base import get_path_info from django.core.handlers.wsgi import WSGIHandler from django.contrib.staticfiles import utils Loading Loading @@ -67,6 +68,6 @@ class StaticFilesHandler(WSGIHandler): return super(StaticFilesHandler, self).get_response(request) def __call__(self, environ, start_response): if not self._should_handle(environ['PATH_INFO']): if not self._should_handle(get_path_info(environ)): return self.application(environ, start_response) return super(StaticFilesHandler, self).__call__(environ, start_response) django/core/handlers/base.py +28 −15 Original line number Diff line number Diff line Loading @@ -5,10 +5,14 @@ import sys import types from django import http from django.conf import settings from django.core import exceptions from django.core import urlresolvers from django.core import signals from django.utils.encoding import force_text from django.utils.importlib import import_module from django.utils import six from django.views import debug logger = logging.getLogger('django.request') Loading @@ -32,8 +36,6 @@ class BaseHandler(object): Must be called after the environment is fixed (see __call__ in subclasses). """ from django.conf import settings from django.core import exceptions self._view_middleware = [] self._template_response_middleware = [] self._response_middleware = [] Loading Loading @@ -75,9 +77,6 @@ class BaseHandler(object): def get_response(self, request): "Returns an HttpResponse object for the given HttpRequest" from django.core import exceptions, urlresolvers from django.conf import settings try: # Setup default url resolver for this thread, this code is outside # the try/except so we don't get a spurious "unbound local Loading Loading @@ -147,7 +146,6 @@ class BaseHandler(object): 'request': request }) if settings.DEBUG: from django.views import debug response = debug.technical_404_response(request, e) else: try: Loading Loading @@ -204,8 +202,6 @@ class BaseHandler(object): caused by anything, so assuming something like the database is always available would be an error. """ from django.conf import settings if settings.DEBUG_PROPAGATE_EXCEPTIONS: raise Loading @@ -218,7 +214,6 @@ class BaseHandler(object): ) if settings.DEBUG: from django.views import debug return debug.technical_500_response(request, *exc_info) # If Http500 handler is not installed, re-raise last exception Loading @@ -238,6 +233,20 @@ class BaseHandler(object): response = func(request, response) return response def get_path_info(environ): """ Returns the HTTP request's PATH_INFO as a unicode string. """ path_info = environ.get('PATH_INFO', str('/')) # Under Python 3, strings in environ are decoded with ISO-8859-1; # re-encode to recover the original bytestring provided by the webserver. if six.PY3: path_info = path_info.encode('iso-8859-1') # It'd be better to implement URI-to-IRI decoding, see #19508. return path_info.decode('utf-8') def get_script_name(environ): """ Returns the equivalent of the HTTP request's SCRIPT_NAME environment Loading @@ -246,7 +255,6 @@ def get_script_name(environ): from the client's perspective), unless the FORCE_SCRIPT_NAME setting is set (to anything). """ from django.conf import settings if settings.FORCE_SCRIPT_NAME is not None: return force_text(settings.FORCE_SCRIPT_NAME) Loading @@ -255,9 +263,14 @@ def get_script_name(environ): # rewrites. Unfortunately not every Web server (lighttpd!) passes this # information through all the time, so FORCE_SCRIPT_NAME, above, is still # needed. script_url = environ.get('SCRIPT_URL', '') if not script_url: script_url = environ.get('REDIRECT_URL', '') script_url = environ.get('SCRIPT_URL', environ.get('REDIRECT_URL', str(''))) if script_url: return force_text(script_url[:-len(environ.get('PATH_INFO', ''))]) return force_text(environ.get('SCRIPT_NAME', '')) script_name = script_url[:-len(environ.get('PATH_INFO', str('')))] else: script_name = environ.get('SCRIPT_NAME', str('')) # Under Python 3, strings in environ are decoded with ISO-8859-1; # re-encode to recover the original bytestring provided by the webserver. if six.PY3: script_name = script_name.encode('iso-8859-1') # It'd be better to implement URI-to-IRI decoding, see #19508. return script_name.decode('utf-8') django/core/handlers/wsgi.py +1 −1 Original line number Diff line number Diff line Loading @@ -128,7 +128,7 @@ class LimitedStream(object): class WSGIRequest(http.HttpRequest): def __init__(self, environ): script_name = base.get_script_name(environ) path_info = force_text(environ.get('PATH_INFO', '/')) path_info = base.get_path_info(environ) if not path_info or path_info == script_name: # Sometimes PATH_INFO exists, but is empty (e.g. accessing # the SCRIPT_NAME URL without a trailing slash). We really need to Loading django/test/client.py +5 −1 Original line number Diff line number Diff line Loading @@ -245,7 +245,11 @@ class RequestFactory(object): # If there are parameters, add them if parsed[3]: path += str(";") + force_str(parsed[3]) return unquote(path) path = unquote(path) # WSGI requires latin-1 encoded strings. See get_path_info(). if six.PY3: path = path.encode('utf-8').decode('iso-8859-1') return path def get(self, path, data={}, **extra): "Construct a GET request." Loading tests/regressiontests/handlers/tests.py +2 −1 Original line number Diff line number Diff line from django.core.handlers.wsgi import WSGIHandler from django.test import RequestFactory from django.test.utils import override_settings from django.utils import six from django.utils import unittest class HandlerTests(unittest.TestCase): Loading @@ -22,7 +23,7 @@ class HandlerTests(unittest.TestCase): def test_bad_path_info(self): """Tests for bug #15672 ('request' referenced before assignment)""" environ = RequestFactory().get('/').environ environ['PATH_INFO'] = b'\xed' environ['PATH_INFO'] = '\xed' handler = WSGIHandler() response = handler(environ, lambda *a, **k: None) self.assertEqual(response.status_code, 400) Loading
django/contrib/staticfiles/handlers.py +2 −1 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ except ImportError: # Python 2 from urlparse import urlparse from django.conf import settings from django.core.handlers.base import get_path_info from django.core.handlers.wsgi import WSGIHandler from django.contrib.staticfiles import utils Loading Loading @@ -67,6 +68,6 @@ class StaticFilesHandler(WSGIHandler): return super(StaticFilesHandler, self).get_response(request) def __call__(self, environ, start_response): if not self._should_handle(environ['PATH_INFO']): if not self._should_handle(get_path_info(environ)): return self.application(environ, start_response) return super(StaticFilesHandler, self).__call__(environ, start_response)
django/core/handlers/base.py +28 −15 Original line number Diff line number Diff line Loading @@ -5,10 +5,14 @@ import sys import types from django import http from django.conf import settings from django.core import exceptions from django.core import urlresolvers from django.core import signals from django.utils.encoding import force_text from django.utils.importlib import import_module from django.utils import six from django.views import debug logger = logging.getLogger('django.request') Loading @@ -32,8 +36,6 @@ class BaseHandler(object): Must be called after the environment is fixed (see __call__ in subclasses). """ from django.conf import settings from django.core import exceptions self._view_middleware = [] self._template_response_middleware = [] self._response_middleware = [] Loading Loading @@ -75,9 +77,6 @@ class BaseHandler(object): def get_response(self, request): "Returns an HttpResponse object for the given HttpRequest" from django.core import exceptions, urlresolvers from django.conf import settings try: # Setup default url resolver for this thread, this code is outside # the try/except so we don't get a spurious "unbound local Loading Loading @@ -147,7 +146,6 @@ class BaseHandler(object): 'request': request }) if settings.DEBUG: from django.views import debug response = debug.technical_404_response(request, e) else: try: Loading Loading @@ -204,8 +202,6 @@ class BaseHandler(object): caused by anything, so assuming something like the database is always available would be an error. """ from django.conf import settings if settings.DEBUG_PROPAGATE_EXCEPTIONS: raise Loading @@ -218,7 +214,6 @@ class BaseHandler(object): ) if settings.DEBUG: from django.views import debug return debug.technical_500_response(request, *exc_info) # If Http500 handler is not installed, re-raise last exception Loading @@ -238,6 +233,20 @@ class BaseHandler(object): response = func(request, response) return response def get_path_info(environ): """ Returns the HTTP request's PATH_INFO as a unicode string. """ path_info = environ.get('PATH_INFO', str('/')) # Under Python 3, strings in environ are decoded with ISO-8859-1; # re-encode to recover the original bytestring provided by the webserver. if six.PY3: path_info = path_info.encode('iso-8859-1') # It'd be better to implement URI-to-IRI decoding, see #19508. return path_info.decode('utf-8') def get_script_name(environ): """ Returns the equivalent of the HTTP request's SCRIPT_NAME environment Loading @@ -246,7 +255,6 @@ def get_script_name(environ): from the client's perspective), unless the FORCE_SCRIPT_NAME setting is set (to anything). """ from django.conf import settings if settings.FORCE_SCRIPT_NAME is not None: return force_text(settings.FORCE_SCRIPT_NAME) Loading @@ -255,9 +263,14 @@ def get_script_name(environ): # rewrites. Unfortunately not every Web server (lighttpd!) passes this # information through all the time, so FORCE_SCRIPT_NAME, above, is still # needed. script_url = environ.get('SCRIPT_URL', '') if not script_url: script_url = environ.get('REDIRECT_URL', '') script_url = environ.get('SCRIPT_URL', environ.get('REDIRECT_URL', str(''))) if script_url: return force_text(script_url[:-len(environ.get('PATH_INFO', ''))]) return force_text(environ.get('SCRIPT_NAME', '')) script_name = script_url[:-len(environ.get('PATH_INFO', str('')))] else: script_name = environ.get('SCRIPT_NAME', str('')) # Under Python 3, strings in environ are decoded with ISO-8859-1; # re-encode to recover the original bytestring provided by the webserver. if six.PY3: script_name = script_name.encode('iso-8859-1') # It'd be better to implement URI-to-IRI decoding, see #19508. return script_name.decode('utf-8')
django/core/handlers/wsgi.py +1 −1 Original line number Diff line number Diff line Loading @@ -128,7 +128,7 @@ class LimitedStream(object): class WSGIRequest(http.HttpRequest): def __init__(self, environ): script_name = base.get_script_name(environ) path_info = force_text(environ.get('PATH_INFO', '/')) path_info = base.get_path_info(environ) if not path_info or path_info == script_name: # Sometimes PATH_INFO exists, but is empty (e.g. accessing # the SCRIPT_NAME URL without a trailing slash). We really need to Loading
django/test/client.py +5 −1 Original line number Diff line number Diff line Loading @@ -245,7 +245,11 @@ class RequestFactory(object): # If there are parameters, add them if parsed[3]: path += str(";") + force_str(parsed[3]) return unquote(path) path = unquote(path) # WSGI requires latin-1 encoded strings. See get_path_info(). if six.PY3: path = path.encode('utf-8').decode('iso-8859-1') return path def get(self, path, data={}, **extra): "Construct a GET request." Loading
tests/regressiontests/handlers/tests.py +2 −1 Original line number Diff line number Diff line from django.core.handlers.wsgi import WSGIHandler from django.test import RequestFactory from django.test.utils import override_settings from django.utils import six from django.utils import unittest class HandlerTests(unittest.TestCase): Loading @@ -22,7 +23,7 @@ class HandlerTests(unittest.TestCase): def test_bad_path_info(self): """Tests for bug #15672 ('request' referenced before assignment)""" environ = RequestFactory().get('/').environ environ['PATH_INFO'] = b'\xed' environ['PATH_INFO'] = '\xed' handler = WSGIHandler() response = handler(environ, lambda *a, **k: None) self.assertEqual(response.status_code, 400)