1
0
mirror of https://github.com/django/django.git synced 2025-07-04 01:39:20 +00:00

[soc2009/http-wsgi-improvements] Establish the priorities and fallbacks for HttpResponseSendFile methods.

Change the setting to settings.HTTPRESPONSE_SENDFILE_METHOD. If this is set to None, we use handler methods,
but otherwise the header gets set, and we do not send any content. If neither of these are available,
use the FileWrapper fallback in HttpResponseSendFile.

This passes the test suite, but is untested on mod_python. I am still trying to figure out how to
view the headers of a response with the Content-Disposition "attachment."

git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/http-wsgi-improvements@11268 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Chris Cahoon 2009-07-18 02:02:57 +00:00
parent b0e381929f
commit 94a94bee3b
5 changed files with 28 additions and 22 deletions

View File

@ -237,8 +237,12 @@ MEDIA_ROOT = ''
MEDIA_URL = ''
# Header to use in HttpResponseSendFile to inform the handler to serve the
# file with efficient handler-specific routines.
HTTPRESPONSE_SENDFILE_HEADER = 'X-Sendfile'
# file with efficient handler-specific routines. None causes HttpResponseSendFile
# to fall back to, first, mechanisms in the handler (wsgi.filewrapper and
# req.sendfile.
# Examples: 'X-Sendfile' (FastCGI, lighttpd, Apache with mod_xsendfile),
# 'X-Accel-Redirect' (nginx)
HTTPRESPONSE_SENDFILE_METHOD = None
# List of upload handler classes to be applied in order.
FILE_UPLOAD_HANDLERS = (

View File

@ -203,12 +203,12 @@ class ModPythonHandler(BaseHandler):
if isinstance(response, http.HttpResponseSendFile):
req.sendfile(response.sendfile_filename)
else:
try:
for chunk in response:
req.write(chunk)
finally:
response.close()
# If we are using a header to do sendfile, set the header and send empty content
if settings.RESPONSE_SENDFILE_METHOD:
response.set_empty_content()
response[settings.HTTPRESPONSE_SENDFILE_METHOD] = response.sendfile_filename
for chunk in response:
req.write(chunk)
return 0 # mod_python.apache.OK
def handler(req):

View File

@ -243,14 +243,11 @@ class WSGIHandler(base.BaseHandler):
start_response(status, response_headers)
if isinstance(response, http.HttpResponseSendFile):
filelike = open(response.sendfile_filename, 'rb')
if 'wsgi.file_wrapper' in environ:
if settings.HTTPRESPONSE_SENDFILE_METHOD:
response[settings.HTTPRESPONSE_SENDFILE_METHOD] = response.sendfile_filename
elif 'wsgi.file_wrapper' in environ:
filelike = open(response.sendfile_filename, 'rb')
return environ['wsgi.file_wrapper'](filelike,
response.block_size)
else:
# wraps close() as well
from django.core.servers.basehttp import FileWrapper
return FileWrapper(filelike, response.block_size)
return response

View File

@ -447,9 +447,14 @@ class HttpResponseSendFile(HttpResponse):
self['Content-Length'] = os.path.getsize(path_to_file)
self['Content-Disposition'] = ('attachment; filename=%s' %
os.path.basename(path_to_file))
self[settings.HTTPRESPONSE_SENDFILE_HEADER] = path_to_file
self._empty_content = False
def set_empty_content(self):
self._empty_content = True
def __iter__(self):
if self._empty_content:
return iter([''])
from django.core.servers.basehttp import FileWrapper
return FileWrapper(self.get_file_handler(), self.block_size)

View File

@ -18,8 +18,8 @@ class SendFileTests(TestCase):
urllib.quote(file1.name))
self.assertEqual(response.status_code, 200)
self.assertEqual(response[settings.HTTPRESPONSE_SENDFILE_HEADER],
file1.name)
#self.assertEqual(response[settings.HTTPRESPONSE_SENDFILE_METHOD],
# file1.name)
self.assertEqual(response['Content-Disposition'],
'attachment; filename=%s' % os.path.basename(file1.name))
self.assertEqual(response['Content-Length'], str(FILE_SIZE))