Django – Understanding X-Sendfile

Question:

I’ve been doing some research regarding file downloads with access control, using Django. My goal is to completely block access to a file, except when accessed by a specific user. I’ve read that when using Django, X-Sendfile is one of the methods of choice for achieving this (based on other SO questions, etc). My rudimentary understanding of using X-Sendfile with Django is:

  1. User requests URI to get a protected file
  2. Django app decides which file to return based on URL, and checks user permission, etc.
  3. Django app returns an HTTP Response with the ‘X-Sendfile’ header set to the server’s file path
  4. The web server finds the file and returns it to the requester (I assume the webs server also strips out the ‘X-Sendfile’ header along the way)

Compared with chucking the file directly from Django, X-Sendfile seems likely to be a more efficient method of achieving protected downloads (since I can rely on Nginx to serve files, vs Django), but leaves 2 questions for me:

  1. Is my explanation of X-Sendfile at least abstractly correct?
  2. Is it really secure, assuming I don’t provide normal, front-end HTTP access (e.g. http://www.example.com/downloads/secret-file.jpg) to the directory that the file is stored (ie, don’t keep it in my public_html directory)? Or, could a tech-savvy user examine headers, etc. and reverse engineer a way to access a file (to then distribute)?
  3. Is it really a big difference in performance. Am I going to bog my application server down by providing 8b chunked downloads of 150Mb files directly from Django, or is this sort-of a non-issue? The reason I ask is because if both versions are near equal, the Django version would be preferable due to my ability to do things in Python, like log the number of completed downloads, tally bandwidth of downloads etc.

Thanks in advance.

Asked By: orokusaki

||

Answers:

  1. Yes, that’s just how it works.
  2. The exact implementation depends on the webserver but in the case of nginx, it’s recommended to mark the location as internal to prevent external access.
  3. Nginx can asynchronously serve files while with Django you need one thread per request which can get problematic for higher numbers of parallel requests.

Remember to send a X-Accel-Redirect header for nginx instead of X-Sendfile.
See http://wiki.nginx.org/XSendfile for more information.

Answered By: Julian