Permalink
Browse files

[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
  • Loading branch information...
1 parent 9eab311 commit ab67a69ec6d33b6e2bd948fbb8b68e90c804ebab @ccahoon ccahoon committed Jul 10, 2009
Showing with 13 additions and 6 deletions.
  1. +9 −3 django/http/__init__.py
  2. +4 −3 tests/regressiontests/sendfile/tests.py
View
@@ -430,6 +430,8 @@ def tell(self):
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 @@ def __init__(self, path_to_file, content_type=None, block_size=8192):
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
@@ -25,10 +25,11 @@ def test_sendfile(self):
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

0 comments on commit ab67a69

Please sign in to comment.