diff --git a/README.rst b/README.rst index 76ccf99..e611e68 100644 --- a/README.rst +++ b/README.rst @@ -11,13 +11,13 @@ The interface is a single function `sendfile(request, filename, attachment=False :: from sendfile import sendfile - + # send myfile.pdf to user return sendfile(request, '/home/john/myfile.pdf') # send myfile.pdf as an attachment (with name myfile.pdf) return sendfile(request, '/home/john/myfile.pdf', attachment=True) - + # send myfile.pdf as an attachment with a different name return sendfile(request, '/home/john/myfile.pdf', attachment=True, attachment_filename='full-name.pdf') @@ -134,8 +134,13 @@ Then the matching location block in nginx.conf would be: You need to pay attention to whether you have trailing slashes or not on the SENDFILE_URL and root values, otherwise you may not get the right URL being sent to NGINX and you may get 404s. You should be able to see what file NGINX is trying to load in the error.log if this happens. From there it should be fairly easy to work out what the right settings are. +Also if you are willing to use django-sendfile with Nginx older than 1.5.9, you need to setup the configuration setting in django settings for specifying Nginx version like this: + +:: + + NGINX_VERSION = '1.4.6' + .. _mod_xsendfile: https://tn123.org/mod_xsendfile/ .. _Apache: http://httpd.apache.org/ .. _Lighthttpd: http://www.lighttpd.net/ .. _mod_wsgi: http://code.google.com/p/modwsgi/ - diff --git a/sendfile/backends/_internalredirect.py b/sendfile/backends/_internalredirect.py index be4e069..b234476 100644 --- a/sendfile/backends/_internalredirect.py +++ b/sendfile/backends/_internalredirect.py @@ -2,6 +2,7 @@ from django.conf import settings from django.utils.encoding import smart_text, smart_bytes +from django.conf import settings try: from urllib.parse import quote @@ -9,6 +10,28 @@ from urllib import quote +def _decision(fn): + _cached_decision = [] + def _decorated(): + if not _cached_decision: + _cached_decision.append(fn()) + return _cached_decision[0] + return _decorated + +@_decision +def should_be_quoted(): + backend = getattr(settings, 'SENDFILE_BACKEND', None) + if backend == 'sendfile.backends.nginx': + nginx_version = getattr(settings, 'NGINX_VERSION', None) + if nginx_version: + nginx_version = map(int, nginx_version.split('.')) + # Since Starting with Nginx 1.5.9, quoted url's are expected to be + # sent with X-Accel-Redirect headers, we will not quote url's for + # versions of Nginx before 1.5.9 + if nginx_version < [1, 5, 9]: + return False + return True + def _convert_file_to_url(filename): relpath = os.path.relpath(filename, settings.SENDFILE_ROOT) @@ -21,4 +44,7 @@ def _convert_file_to_url(filename): # Python3 urllib.parse.quote accepts both unicode and bytes, while Python2 urllib.quote only accepts bytes. # So use bytes for quoting and then go back to unicode. url = [smart_bytes(url_component) for url_component in url] - return smart_text(quote(b'/'.join(url))) + if should_be_quoted(): + return smart_text(quote(b'/'.join(url))) + else: + return smart_text(b'/'.join(url))