Commit a8ab309f authored by Cristi Vîjdea's avatar Cristi Vîjdea
Browse files

Support X-Accel-Redirect in nginx >=1.5.9

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.

The ``PRIVATE_STORAGE_NGINX_VERSION`` setting is used to determine the proper encoding (defaults to current behaviour of not quoting).

https://github.com/adnrs96/django-sendfile/commit/4488e520f04661136e88be38281e789ae50a260c
parent 967be0df
......@@ -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,10 @@ 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.
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)
# preserve old behaviour by default to avoid breaking compatibility
return False
@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