Unverified Commit f6223eea authored by Diederik van der Boor's avatar Diederik van der Boor Committed by GitHub
Browse files

Merge pull request #20 from axnsan12/nginx-x-accel-quote

 Support X-Accel-Redirect quoting in nginx >=1.5.9
parents bab6d253 012c7580
......@@ -15,3 +15,5 @@ build/
dist/
docs/_build/
htmlcov/
venv/
.venv/
Changelog
=========
Changes in x.y (Date TBD)
---------------------------
* Fixed ``X-Accel-Redirect`` non-ascii filename URI encoding compatiblity with ``nginx`` >= 1.5.9.
* the ``PRIVATE_STORAGE_NGINX_VERSION`` is now used to determine proper behaviour, which defaults to assuming >=1.5.9
Changes in 2.1 (2018-05-08)
---------------------------
......
......@@ -202,6 +202,7 @@ For Nginx
PRIVATE_STORAGE_SERVER = 'nginx'
PRIVATE_STORAGE_INTERNAL_URL = '/private-x-accel-redirect/'
PRIVATE_STORAGE_NGINX_VERSION = 'your.nginx.version'
Add the following location block in the server config:
......@@ -212,6 +213,13 @@ Add the following location block in the server config:
alias /path/to/private-media/;
}
The ``PRIVATE_STORAGE_NGINX_VERSION`` setting is used to determine the proper encoding of the ``X-Accel-Redirect``
header when dealing with non-ascii file names. Specifically, versions starting with ``1.5.9`` expect the value of the
header to be URL encoded, while older versions require the raw/MIME encoded file path.
The default behaviour is to quote the header (nginx >= 1.5.9), so you have to assign this setting if your nginx
version is lower than that.
Other webservers
~~~~~~~~~~~~~~~~
......
......@@ -7,5 +7,6 @@ PRIVATE_STORAGE_AUTH_FUNCTION = getattr(settings, 'PRIVATE_STORAGE_AUTH_FUNCTION
# For Nginx X-Accel-Redirect
PRIVATE_STORAGE_INTERNAL_URL = getattr(settings, 'PRIVATE_STORAGE_INTERNAL_URL', '/private-x-accel-redirect/')
PRIVATE_STORAGE_NGINX_VERSION = getattr(settings, 'PRIVATE_STORAGE_NGINX_VERSION', None)
PRIVATE_STORAGE_S3_REVERSE_PROXY = getattr(settings, 'PRIVATE_STORAGE_S3_REVERSE_PROXY', False)
......@@ -14,6 +14,13 @@ from django.utils.lru_cache import lru_cache
from django.utils.module_loading import import_string
from django.views.static import serve, was_modified_since
try:
# python 3
from urllib.parse import quote
except ImportError:
# python 2
from urllib import quote
@lru_cache()
def get_server_class(path):
......@@ -45,6 +52,7 @@ def add_no_cache_headers(func):
response['Expires'] = 'Thu, 01 Jan 1970 00:00:00 GMT' # HTTP 1.0 proxies
response['Cache-Control'] = 'max-age=0, no-cache, must-revalidate, proxy-revalidate' # HTTP 1.1
return response
return _dec
......@@ -135,10 +143,30 @@ class NginxXAccelRedirectServer(object):
Or update the ``PRIVATE_STORAGE_INTERNAL_URL`` setting to use a different URL prefix.
"""
@staticmethod
def should_quote():
# newer versions of nginx require a properly encoded URI in the X-Accel-Redirected response
# according to research done by people on the django-sendfile issue tracker, the specific
# version number seems to be 1.5.9
# https://github.com/adnrs96/django-sendfile/commit/4488e520f04661136e88be38281e789ae50a260c
nginx_version = getattr(settings, 'PRIVATE_STORAGE_NGINX_VERSION', None)
if nginx_version:
nginx_version = tuple(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
return nginx_version >= (1, 5, 9)
# nginx 1.5.9 was released in 2014, so just assume most people have that
return True
@staticmethod
@add_no_cache_headers
def serve(private_file):
internal_url = os.path.join(settings.PRIVATE_STORAGE_INTERNAL_URL, private_file.relative_name)
if NginxXAccelRedirectServer.should_quote():
internal_url = quote(internal_url)
response = HttpResponse()
response['X-Accel-Redirect'] = internal_url
response['Content-Type'] = private_file.content_type
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment