From ab67a69ec6d33b6e2bd948fbb8b68e90c804ebab Mon Sep 17 00:00:00 2001 From: Chris Cahoon Date: Fri, 10 Jul 2009 19:02:34 +0000 Subject: [PATCH] [soc2009/http-wsgi-improvements] HttpResponseSendFile now uses django.core.servers.basehttp.FileWrapper inside __iter__ to provide fallback. regressiontests.sendfile uses this now, and passes. The fallback was tested using guppy and apache2 with mod_wsgi for heap issues, and it appears to be fine. We can go back and look at this again if it becomes an issue. git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/http-wsgi-improvements@11212 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/http/__init__.py | 12 +++++++++--- tests/regressiontests/sendfile/tests.py | 7 ++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/django/http/__init__.py b/django/http/__init__.py index a67dbdc949..6de8ed4940 100644 --- a/django/http/__init__.py +++ b/django/http/__init__.py @@ -430,6 +430,8 @@ class HttpResponse(object): return sum([len(chunk) for chunk in self._container]) class HttpResponseSendFile(HttpResponse): + sendfile_fh = None + def __init__(self, path_to_file, content_type=None, block_size=8192): if not content_type: from mimetypes import guess_type @@ -445,10 +447,14 @@ class HttpResponseSendFile(HttpResponse): os.path.basename(path_to_file)) self[settings.HTTPRESPONSE_SENDFILE_HEADER] = path_to_file - def _get_content(self): - return open(self.sendfile_filename).read() + def __iter__(self): + from django.core.servers.basehttp import FileWrapper + return FileWrapper(self.get_file_handler(), self.block_size) - content = property(_get_content) + def get_file_handler(self): + if not self.sendfile_fh: + self.sendfile_fh = open(self.sendfile_filename, 'rb') + return self.sendfile_fh class HttpResponseRedirect(HttpResponse): _status_code = 302 diff --git a/tests/regressiontests/sendfile/tests.py b/tests/regressiontests/sendfile/tests.py index cdae1db60f..b28cb2ead8 100644 --- a/tests/regressiontests/sendfile/tests.py +++ b/tests/regressiontests/sendfile/tests.py @@ -25,10 +25,11 @@ class SendFileTests(TestCase): self.assertEqual(response['Content-Length'], str(FILE_SIZE)) self.assertEqual(response['Content-Type'], 'application/pdf') - # *if* the degraded case is to be supported, add this instead: - self.assertEqual(response.content, CONTENT) + # Test the fallback file transfer -- we use FileWrapper to iterate through + # the file, this also wraps close(). This appears to mitigate performance + # issues. + self.assertEqual("".join(iter(response)), CONTENT) get_content = lambda: response.content.read() - #self.assertRaises(TypeError, get_content) file1.close() # TODO: test middleware bypass etc