Commits

Anonymous committed 294bd99

[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.

Comments (0)

Files changed (2)

django/http/__init__.py

         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 
  	            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

tests/regressiontests/sendfile/tests.py

         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
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.