Commits

cca...@bcc190cf-cafb-0310-a4f2-bffc1f526a37  committed ba9c95c

[soc2009/http-wsgi-improvements] Changes for ``HttpResponseSendFile`` support in FastCGI. Refs #2131.

  • Participants
  • Parent commits 50d454e
  • Branches soc2009/http-wsgi-improvements

Comments (0)

Files changed (6)

File django/conf/global_settings.py

 # 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),
+# Examples: 'X-Sendfile' (lighttpd & Cherokee with FastCGI/SCGI, Apache with mod_xsendfile),
 #           'X-Accel-Redirect' (nginx)
-HTTPRESPONSE_SENDFILE_METHOD = None
+HTTPRESPONSE_SENDFILE_HEADER = None
 
 # List of upload handler classes to be applied in order.
 FILE_UPLOAD_HANDLERS = (

File django/core/handlers/modpython.py

             req.sendfile(response.sendfile_filename)
         else:
             # If we are using a header to do sendfile, set the header and send empty content
-            if settings.RESPONSE_SENDFILE_METHOD:
+            if settings.RESPONSE_SENDFILE_HEADER:
                 response.set_empty_content()
-                response[settings.HTTPRESPONSE_SENDFILE_METHOD] = response.sendfile_filename
+                response[settings.HTTPRESPONSE_SENDFILE_HEADER] = response.sendfile_filename
             for chunk in response:
                 req.write(chunk)
         return 0 # mod_python.apache.OK

File django/core/handlers/wsgi.py

             response_headers.append(('Set-Cookie', str(c.output(header=''))))
         
         if isinstance(response, http.HttpResponseSendFile): 
-            if settings.HTTPRESPONSE_SENDFILE_METHOD:
-                response_headers.append((settings.HTTPRESPONSE_SENDFILE_METHOD,
-                    response.sendfile_filename))
+            filename = response.sendfile_filename
+            if settings.HTTPRESPONSE_SENDFILE_HEADER:
+                response.set_empty_content()
+                response_headers.append((settings.HTTPRESPONSE_SENDFILE_HEADER,
+                    filename))
             elif 'wsgi.file_wrapper' in environ:
-                filelike = open(response.sendfile_filename, 'rb')
+                filelike = open(filename, 'rb')
                 return environ['wsgi.file_wrapper'](filelike, 
                         response.block_size)
-
+            else:
+                import os.path
+                if not os.path.exists(filename):
+                     raise Exception("Filename provided to HttpResponseSendFile does not exist.")
+                response_headers.append(('Content-Length', 
+                                         str(os.path.getsize(filename))))
         start_response(status, response_headers)
         return response
 

File django/http/__init__.py

         super(HttpResponseSendFile, self).__init__('', content_type=content_type)
         self.sendfile_filename = path_to_file
         self.block_size = block_size
-        self['Content-Length'] = os.path.getsize(path_to_file)
         self['Content-Disposition'] = ('attachment; filename=%s' %
              os.path.basename(path_to_file))
         self._empty_content = False

File docs/ref/request-response.txt

     optionally, the file's content type and block size hint for handlers that
     need it.
 
+    If the setting ``HTTPRESPONSE_SENDFILE_HEADER`` is overridden (default None),
+    HttpResponseSendFile will return that response header set as the file name given.
+    If the file is unavailable, no content will be returned. Since certain servers
+    do not allow direct access to the file system, it is not feasible to verify
+    the file's existence beforehand.
+
+    Be very careful with this method. It provides access to the filesystem that 
+    must be controlled, and performs no verification of a file's existence in most
+    cases.
+
     Note that response middleware will be bypassed if you use
     :class:`HttpResponseSendFile`.
 

File tests/regressiontests/sendfile/tests.py

                 urllib.quote(file1.name))
 
         self.assertEqual(response.status_code, 200)
-        #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))