Skip to content

Commit d69f33f

Browse files
committed
backends-nginx: Add support for Nginx versions older than 1.5.9.
In this commit we are adding support for Nginx version older than 1.5.9. This is achieved through conditionally quoting the URL's in X-Accel-Redirect headers according to compatibility with Nginx. Since newer versions of Nginx expect URL's in X-Accel-Redirect to be quoted unlike the versions older that Nginx 1.5.9. From this commit onwards we start to expect a 'NGINX_VERSION' config setting to be setup in the django settings in order to facilitate decision making regarding quoting URL's. If such a setting is not found we just assume Nginx version to be greater then 1.5.9 and make decision accordingly and then cache the decision by making use of a decorator. Using this result we decide whether the outgoing URL should be quoted or not. Fixes: #56, #58. Closes #45.
1 parent b99f963 commit d69f33f

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

README.rst

+8-3
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ The interface is a single function `sendfile(request, filename, attachment=False
1111
::
1212

1313
from sendfile import sendfile
14-
14+
1515
# send myfile.pdf to user
1616
return sendfile(request, '/home/john/myfile.pdf')
1717

1818
# send myfile.pdf as an attachment (with name myfile.pdf)
1919
return sendfile(request, '/home/john/myfile.pdf', attachment=True)
20-
20+
2121
# send myfile.pdf as an attachment with a different name
2222
return sendfile(request, '/home/john/myfile.pdf', attachment=True, attachment_filename='full-name.pdf')
2323

@@ -134,8 +134,13 @@ Then the matching location block in nginx.conf would be:
134134

135135
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.
136136

137+
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:
138+
139+
::
140+
141+
NGINX_VERSION = '1.4.6'
142+
137143
.. _mod_xsendfile: https://tn123.org/mod_xsendfile/
138144
.. _Apache: http://httpd.apache.org/
139145
.. _Lighthttpd: http://www.lighttpd.net/
140146
.. _mod_wsgi: http://code.google.com/p/modwsgi/
141-

sendfile/backends/_internalredirect.py

+27-1
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,36 @@
22

33
from django.conf import settings
44
from django.utils.encoding import smart_text, smart_bytes
5+
from django.conf import settings
56

67
try:
78
from urllib.parse import quote
89
except ImportError:
910
from urllib import quote
1011

1112

13+
def _decision(fn):
14+
_cached_decision = []
15+
def _decorated():
16+
if not _cached_decision:
17+
_cached_decision.append(fn())
18+
return _cached_decision[0]
19+
return _decorated
20+
21+
@_decision
22+
def should_be_quoted():
23+
backend = getattr(settings, 'SENDFILE_BACKEND', None)
24+
if backend == 'sendfile.backends.nginx':
25+
nginx_version = getattr(settings, 'NGINX_VERSION', None)
26+
if nginx_version:
27+
nginx_version = map(int, nginx_version.split('.'))
28+
# Since Starting with Nginx 1.5.9, quoted url's are expected to be
29+
# sent with X-Accel-Redirect headers, we will not quote url's for
30+
# versions of Nginx before 1.5.9
31+
if nginx_version < [1, 5, 9]:
32+
return False
33+
return True
34+
1235
def _convert_file_to_url(filename):
1336
relpath = os.path.relpath(filename, settings.SENDFILE_ROOT)
1437

@@ -21,4 +44,7 @@ def _convert_file_to_url(filename):
2144
# Python3 urllib.parse.quote accepts both unicode and bytes, while Python2 urllib.quote only accepts bytes.
2245
# So use bytes for quoting and then go back to unicode.
2346
url = [smart_bytes(url_component) for url_component in url]
24-
return smart_text(quote(b'/'.join(url)))
47+
if should_be_quoted():
48+
return smart_text(quote(b'/'.join(url)))
49+
else:
50+
return smart_text(b'/'.join(url))

0 commit comments

Comments
 (0)