Skip to content

Commit f45fac5

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: johnsensible#56, johnsensible#58. Closes johnsensible#45.
1 parent b99f963 commit f45fac5

File tree

2 files changed

+34
-4
lines changed

2 files changed

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

+26-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,28 @@
99
from urllib import quote
1010

1111

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

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

0 commit comments

Comments
 (0)