mirror of
https://github.com/jazzband/django-downloadview.git
synced 2026-03-16 22:40:25 +00:00
195 lines
5.1 KiB
Text
195 lines
5.1 KiB
Text
#####
|
|
Nginx
|
|
#####
|
|
|
|
If you serve Django behind Nginx, then you can delegate the file streaming
|
|
to Nginx and get increased performance:
|
|
|
|
* lower resources used by Python/Django workers ;
|
|
* faster download.
|
|
|
|
See `Nginx X-accel documentation`_ for details.
|
|
|
|
|
|
*****************
|
|
Known limitations
|
|
*****************
|
|
|
|
* Nginx needs access to the resource by URL (proxy) or path (location).
|
|
* Thus :class:`~django_downloadview.files.VirtualFile` and any generated files
|
|
cannot be streamed by Nginx.
|
|
|
|
|
|
************
|
|
Given a view
|
|
************
|
|
|
|
Let's consider the following view:
|
|
|
|
.. literalinclude:: /../demo/demoproject/nginx/views.py
|
|
:language: python
|
|
:lines: 1-6, 8-17
|
|
|
|
What is important here is that the files will have an ``url`` property
|
|
implemented by storage. Let's setup an optimization rule based on that URL.
|
|
|
|
.. note::
|
|
|
|
It is generally easier to setup rules based on URL rather than based on
|
|
name in filesystem. This is because path is generally relative to storage,
|
|
whereas URL usually contains some storage identifier, i.e. it is easier to
|
|
target a specific location by URL rather than by filesystem name.
|
|
|
|
|
|
********************************
|
|
Setup XAccelRedirect middlewares
|
|
********************************
|
|
|
|
Make sure ``django_downloadview.SmartDownloadMiddleware`` is in
|
|
``MIDDLEWARE`` of your `Django` settings.
|
|
|
|
Example:
|
|
|
|
.. literalinclude:: /../demo/demoproject/settings.py
|
|
:language: python
|
|
:lines: 62-69
|
|
|
|
Then set ``django_downloadview.nginx.XAccelRedirectMiddleware`` as
|
|
``DOWNLOADVIEW_BACKEND``:
|
|
|
|
.. literalinclude:: /../demo/demoproject/settings.py
|
|
:language: python
|
|
:lines: 75
|
|
|
|
Then register as many ``DOWNLOADVIEW_RULES`` as you wish:
|
|
|
|
.. literalinclude:: /../demo/demoproject/settings.py
|
|
:language: python
|
|
:lines: 83-88
|
|
|
|
Each item in ``DOWNLOADVIEW_RULES`` is a dictionary of keyword arguments passed
|
|
to the middleware factory. In the example above, we capture responses by
|
|
``source_url`` and convert them to internal redirects to ``destination_url``.
|
|
|
|
.. autoclass:: django_downloadview.nginx.middlewares.XAccelRedirectMiddleware
|
|
:members:
|
|
:inherited-members:
|
|
:undoc-members:
|
|
:show-inheritance:
|
|
:member-order: bysource
|
|
|
|
|
|
**********************************************
|
|
Per-view setup with x_accel_redirect decorator
|
|
**********************************************
|
|
|
|
Middlewares should be enough for most use cases, but you may want per-view
|
|
configuration. For `nginx`, there is ``x_accel_redirect``:
|
|
|
|
.. autofunction:: django_downloadview.nginx.decorators.x_accel_redirect
|
|
|
|
As an example:
|
|
|
|
.. literalinclude:: /../demo/demoproject/nginx/views.py
|
|
:language: python
|
|
:lines: 1-7, 17-
|
|
|
|
|
|
*******************************************
|
|
Test responses with assert_x_accel_redirect
|
|
*******************************************
|
|
|
|
Use :func:`~django_downloadview.nginx.decorators.assert_x_accel_redirect`
|
|
function as a shortcut in your tests.
|
|
|
|
.. literalinclude:: /../demo/demoproject/nginx/tests.py
|
|
:language: python
|
|
|
|
.. autofunction:: django_downloadview.nginx.tests.assert_x_accel_redirect
|
|
|
|
The tests above assert the `Django` part is OK. Now let's configure `nginx`.
|
|
|
|
|
|
***********
|
|
Setup Nginx
|
|
***********
|
|
|
|
See `Nginx X-accel documentation`_ for details.
|
|
|
|
Here is what you could have in :file:`/etc/nginx/sites-available/default`:
|
|
|
|
.. code-block:: nginx
|
|
|
|
charset utf-8;
|
|
|
|
# Django-powered service.
|
|
upstream frontend {
|
|
server 127.0.0.1:8000 fail_timeout=0;
|
|
}
|
|
|
|
server {
|
|
listen 80 default;
|
|
|
|
# File-download proxy.
|
|
#
|
|
# Will serve /var/www/files/myfile.tar.gz when passed URI
|
|
# like /optimized-download/myfile.tar.gz
|
|
#
|
|
# See http://wiki.nginx.org/X-accel
|
|
# and https://django-downloadview.readthedocs.io
|
|
#
|
|
location /proxied-download {
|
|
internal;
|
|
# Location to files on disk.
|
|
alias /var/www/files/;
|
|
}
|
|
|
|
# Proxy to Django-powered frontend.
|
|
location / {
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header Host $http_host;
|
|
proxy_redirect off;
|
|
proxy_pass http://frontend;
|
|
}
|
|
}
|
|
|
|
... where specific configuration is the ``location /optimized-download``
|
|
section.
|
|
|
|
.. note::
|
|
|
|
``/proxied-download`` has the ``internal`` flag, so this location is not
|
|
available for the client, i.e. users are not able to download files via
|
|
``/optimized-download/<filename>``.
|
|
|
|
|
|
*********************************************
|
|
Assert everything goes fine with healthchecks
|
|
*********************************************
|
|
|
|
:doc:`Healthchecks </healthchecks>` are the best way to check the complete
|
|
setup.
|
|
|
|
|
|
*************
|
|
Common issues
|
|
*************
|
|
|
|
``Unknown charset "utf-8" to override``
|
|
=======================================
|
|
|
|
Add ``charset utf-8;`` in your nginx configuration file.
|
|
|
|
``open() "path/to/something" failed (2: No such file or directory)``
|
|
====================================================================
|
|
|
|
Check your ``settings.NGINX_DOWNLOAD_MIDDLEWARE_SOURCE_DIR`` in Django
|
|
configuration VS ``alias`` in nginx configuration: in a standard configuration,
|
|
they should be equal.
|
|
|
|
|
|
.. rubric:: References
|
|
|
|
.. target-notes::
|
|
|
|
.. _`Nginx X-accel documentation`: http://wiki.nginx.org/X-accel
|