##### Nginx ##### If you serve Django behind Nginx, then you can delegate the file download service to Nginx and get increased performance: * lower resources used by Python/Django workers ; * faster download. See `Nginx X-accel documentation`_ for details. **************************** Configure some download view **************************** Let's start in the situation described in the :doc:`demo application `: * a project "demoproject" * an application "demoproject.download" * a :py:class:`django_downloadview.views.ObjectDownloadView` view serves files of a "Document" model. We are to make it more efficient with Nginx. .. note:: Examples below are taken from the :doc:`demo project `. *********** Write tests *********** Use :py:func:`django_downloadview.nginx.assert_x_accel_redirect` function as a shortcut in your tests. :file:`demo/demoproject/nginx/tests.py`: .. literalinclude:: ../../demo/demoproject/nginx/tests.py :language: python :emphasize-lines: 5, 25-34 Right now, this test should fail, since you haven't implemented the view yet. ************ Setup Django ************ At the end of this setup, the test should pass, but you still have to `setup Nginx`_! You have two options: global setup with a middleware, or per-view setup with decorators. Global delegation, with XAccelRedirectMiddleware ================================================ If you want to delegate all file downloads to Nginx, then use :py:class:`django_downloadview.nginx.XAccelRedirectMiddleware`. Register it in your settings: .. code-block:: python MIDDLEWARE_CLASSES = ( # ... 'django_downloadview.nginx.XAccelRedirectMiddleware', # ... ) Setup the middleware: .. code-block:: python NGINX_DOWNLOAD_MIDDLEWARE_MEDIA_ROOT = MEDIA_ROOT # Could be elsewhere. NGINX_DOWNLOAD_MIDDLEWARE_MEDIA_URL = '/proxied-download' Optionally fine-tune the middleware. Default values are ``None``, which means "use Nginx's defaults". .. code-block:: python NGINX_DOWNLOAD_MIDDLEWARE_EXPIRES = False # Force no expiration. NGINX_DOWNLOAD_MIDDLEWARE_WITH_BUFFERING = False # Force buffering off. NGINX_DOWNLOAD_MIDDLEWARE_LIMIT_RATE = False # Force limit rate off. Local delegation, with x_accel_redirect decorator ================================================= If you want to delegate file downloads to Nginx on a per-view basis, then use :py:func:`django_downloadview.nginx.x_accel_redirect` decorator. :file:`demo/demoproject/nginx/views.py`: .. literalinclude:: ../../demo/demoproject/nginx/views.py :language: python And use it in som URL conf, as an example in :file:`demo/demoproject/nginx/urls.py`: .. literalinclude:: ../../demo/demoproject/nginx/urls.py :language: python .. note:: In real life, you'd certainly want to replace the "download_document" view instead of registering a new view. *********** 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://github.com/benoitbryon/django-downloadview location /proxied-download { internal; # Location to files on disk. # See Django's settings.NGINX_DOWNLOAD_MIDDLEWARE_MEDIA_ROOT 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`` is not available for the client, i.e. users won't be able to download files via ``/optimized-download/``. .. warning:: Make sure Nginx can read the files to download! Check permissions. ************* 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_MEDIA_ROOT`` 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