diff -r 6641e941ef1e -r ff1a9aa48cfd app/django/core/handlers/wsgi.py --- a/app/django/core/handlers/wsgi.py Tue Oct 14 12:36:55 2008 +0000 +++ b/app/django/core/handlers/wsgi.py Tue Oct 14 16:00:59 2008 +0000 @@ -7,8 +7,8 @@ from django import http from django.core import signals -from django.core.handlers.base import BaseHandler -from django.dispatch import dispatcher +from django.core.handlers import base +from django.core.urlresolvers import set_script_prefix from django.utils import datastructures from django.utils.encoding import force_unicode @@ -74,10 +74,25 @@ class WSGIRequest(http.HttpRequest): def __init__(self, environ): + script_name = base.get_script_name(environ) + path_info = force_unicode(environ.get('PATH_INFO', u'/')) + 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 + # operate as if they'd requested '/'. Not amazingly nice to force + # the path like this, but should be harmless. + # + # (The comparison of path_info to script_name is to work around an + # apparent bug in flup 1.0.1. Se Django ticket #8490). + path_info = u'/' self.environ = environ - self.path = force_unicode(environ['PATH_INFO']) + self.path_info = path_info + self.path = '%s%s' % (script_name, path_info) self.META = environ + self.META['PATH_INFO'] = path_info + self.META['SCRIPT_NAME'] = script_name self.method = environ['REQUEST_METHOD'].upper() + self._post_parse_error = False def __repr__(self): # Since this is called as part of error handling, we need to be very @@ -86,10 +101,13 @@ get = pformat(self.GET) except: get = '' - try: - post = pformat(self.POST) - except: + if self._post_parse_error: post = '' + else: + try: + post = pformat(self.POST) + except: + post = '' try: cookies = pformat(self.COOKIES) except: @@ -112,9 +130,21 @@ # Populates self._post and self._files if self.method == 'POST': if self.environ.get('CONTENT_TYPE', '').startswith('multipart'): - header_dict = dict([(k, v) for k, v in self.environ.items() if k.startswith('HTTP_')]) - header_dict['Content-Type'] = self.environ.get('CONTENT_TYPE', '') - self._post, self._files = http.parse_file_upload(header_dict, self.raw_post_data) + self._raw_post_data = '' + try: + self._post, self._files = self.parse_file_upload(self.META, self.environ['wsgi.input']) + except: + # An error occured while parsing POST data. Since when + # formatting the error the request handler might access + # self.POST, set self._post and self._file to prevent + # attempts to parse POST data again. + self._post = http.QueryDict('') + self._files = datastructures.MultiValueDict() + # Mark that an error occured. This allows self.__repr__ to + # be explicit about it instead of simply representing an + # empty POST + self._post_parse_error = True + raise else: self._post, self._files = http.QueryDict(self.raw_post_data, encoding=self._encoding), datastructures.MultiValueDict() else: @@ -163,7 +193,10 @@ try: # CONTENT_LENGTH might be absent if POST doesn't have content at all (lighttpd) content_length = int(self.environ.get('CONTENT_LENGTH', 0)) - except ValueError: # if CONTENT_LENGTH was empty string or not an integer + except (ValueError, TypeError): + # If CONTENT_LENGTH was empty string or not an integer, don't + # error out. We've also seen None passed in here (against all + # specs, but see ticket #8259), so we handle TypeError as well. content_length = 0 if content_length > 0: safe_copyfileobj(self.environ['wsgi.input'], buf, @@ -179,7 +212,7 @@ REQUEST = property(_get_request) raw_post_data = property(_get_raw_post_data) -class WSGIHandler(BaseHandler): +class WSGIHandler(base.BaseHandler): initLock = Lock() request_class = WSGIRequest @@ -195,7 +228,8 @@ self.load_middleware() self.initLock.release() - dispatcher.send(signal=signals.request_started) + set_script_prefix(base.get_script_name(environ)) + signals.request_started.send(sender=self.__class__) try: try: request = self.request_class(environ) @@ -209,7 +243,7 @@ response = middleware_method(request, response) response = self.apply_response_fixes(request, response) finally: - dispatcher.send(signal=signals.request_finished) + signals.request_finished.send(sender=self.__class__) try: status_text = STATUS_CODE_TEXT[response.status_code]