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:
parent
b0e381929f
commit
94a94bee3b
@ -237,8 +237,12 @@ MEDIA_ROOT = ''
|
|||||||
MEDIA_URL = ''
|
MEDIA_URL = ''
|
||||||
|
|
||||||
# Header to use in HttpResponseSendFile to inform the handler to serve the
|
# Header to use in HttpResponseSendFile to inform the handler to serve the
|
||||||
# file with efficient handler-specific routines.
|
# file with efficient handler-specific routines. None causes HttpResponseSendFile
|
||||||
HTTPRESPONSE_SENDFILE_HEADER = 'X-Sendfile'
|
# 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.
|
# List of upload handler classes to be applied in order.
|
||||||
FILE_UPLOAD_HANDLERS = (
|
FILE_UPLOAD_HANDLERS = (
|
||||||
|
@ -203,12 +203,12 @@ class ModPythonHandler(BaseHandler):
|
|||||||
if isinstance(response, http.HttpResponseSendFile):
|
if isinstance(response, http.HttpResponseSendFile):
|
||||||
req.sendfile(response.sendfile_filename)
|
req.sendfile(response.sendfile_filename)
|
||||||
else:
|
else:
|
||||||
try:
|
# If we are using a header to do sendfile, set the header and send empty content
|
||||||
for chunk in response:
|
if settings.RESPONSE_SENDFILE_METHOD:
|
||||||
req.write(chunk)
|
response.set_empty_content()
|
||||||
finally:
|
response[settings.HTTPRESPONSE_SENDFILE_METHOD] = response.sendfile_filename
|
||||||
response.close()
|
for chunk in response:
|
||||||
|
req.write(chunk)
|
||||||
return 0 # mod_python.apache.OK
|
return 0 # mod_python.apache.OK
|
||||||
|
|
||||||
def handler(req):
|
def handler(req):
|
||||||
|
@ -243,14 +243,11 @@ class WSGIHandler(base.BaseHandler):
|
|||||||
start_response(status, response_headers)
|
start_response(status, response_headers)
|
||||||
|
|
||||||
if isinstance(response, http.HttpResponseSendFile):
|
if isinstance(response, http.HttpResponseSendFile):
|
||||||
filelike = open(response.sendfile_filename, 'rb')
|
if settings.HTTPRESPONSE_SENDFILE_METHOD:
|
||||||
if 'wsgi.file_wrapper' in environ:
|
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,
|
return environ['wsgi.file_wrapper'](filelike,
|
||||||
response.block_size)
|
response.block_size)
|
||||||
else:
|
|
||||||
# wraps close() as well
|
|
||||||
from django.core.servers.basehttp import FileWrapper
|
|
||||||
return FileWrapper(filelike, response.block_size)
|
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
@ -447,9 +447,14 @@ class HttpResponseSendFile(HttpResponse):
|
|||||||
self['Content-Length'] = os.path.getsize(path_to_file)
|
self['Content-Length'] = os.path.getsize(path_to_file)
|
||||||
self['Content-Disposition'] = ('attachment; filename=%s' %
|
self['Content-Disposition'] = ('attachment; filename=%s' %
|
||||||
os.path.basename(path_to_file))
|
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):
|
def __iter__(self):
|
||||||
|
if self._empty_content:
|
||||||
|
return iter([''])
|
||||||
from django.core.servers.basehttp import FileWrapper
|
from django.core.servers.basehttp import FileWrapper
|
||||||
return FileWrapper(self.get_file_handler(), self.block_size)
|
return FileWrapper(self.get_file_handler(), self.block_size)
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@ class SendFileTests(TestCase):
|
|||||||
urllib.quote(file1.name))
|
urllib.quote(file1.name))
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(response[settings.HTTPRESPONSE_SENDFILE_HEADER],
|
#self.assertEqual(response[settings.HTTPRESPONSE_SENDFILE_METHOD],
|
||||||
file1.name)
|
# file1.name)
|
||||||
self.assertEqual(response['Content-Disposition'],
|
self.assertEqual(response['Content-Disposition'],
|
||||||
'attachment; filename=%s' % os.path.basename(file1.name))
|
'attachment; filename=%s' % os.path.basename(file1.name))
|
||||||
self.assertEqual(response['Content-Length'], str(FILE_SIZE))
|
self.assertEqual(response['Content-Length'], str(FILE_SIZE))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user