Storage and View to send X-Accel-Redirect (or X-Sendfile) header to nginx (or apache) reverse-proxy
Project description
django-reverse-proxy-send-file
Sumary
This package help writing views which use the X-Accel-Redirect
header to have nginx
serving files but still allow a permission check at django's side
Intro
The storage.ReverseProxySendFileStorageFileSystemStorage
class is a drop-in replacement of django's FileSystemStorage
which make FileField (or ImageField) url to use the REVERSE_PROXY_SENDFILE_MEDIA_URL
settings base url instead of MEDIA_URL
The storage.ReverseProxySendFileStorageMixin
allow you to apply the overriden base_url
on any storage class
The ReverseProxySendFileView
class handle GET request and return an empty response with nginx's X-Accel-Redirect
header to order nginx to return the file at given path. The REVERSE_PROXY_SENDFILE_MEDIA_ROOT
setting must be defined in the nginx context si it can find the file
The ReverseProxySendFileView
can be overrided to implement a custom check_permission
method which verify is the current user is allowed to download the resource.
Installation
Install the django-reverse-proxy-send-file
pypi package.
ex:
poetry add django-reverse-proxy-send-file
pip install django-reverse-proxy-send-file
Usage
See example section bellow
Settings
REVERSE_PROXY_SENDFILE_MEDIA_ROOT
Default to django's MEDIA_ROOT
Base path in django's context where to store media files when uploaded (used by Storage class)
REVERSE_PROXY_SENDFILE_MEDIA_URL
Default to "smedia/"
URL that handle the resources that should be served by the reverse proxy.
REVERSE_PROXY_SENDFILE_REVERSE_PROXY_ROOT
Default to "smedia/"
Base path in reverse-proxy's context which is sent back to reverse-proxy in header so it can find the file
REVERSE_PROXY_SENDFILE_MODE
Default to "nginx"
Possible values: "nginx"
or "apache"
nginx
mode will use X-Accel-Redirect
header whereas apache
mode will use X-Sendfile
REVERSE_PROXY_SENDFILE_HEADER_NAME
Default to None
Enter a custom header name. If set this header will be used regardless REVERSE_PROXY_SENDFILE_MODE
setting.
REVERSE_PROXY_SENDFILE_DEBUG_SERVE_RESOURCE
Default to True
In django's DEBUG
mode, the resource is directly served by the dev server.
Exemple
settings.py
...
REVERSE_PROXY_SENDFILE_MEDIA_URL = "smedia/"
REVERSE_PROXY_SENDFILE_MEDIA_ROOT = "/django_path/to/smedia/"
REVERSE_PROXY_SENDFILE_REVERSE_PROXY_ROOT = "/nginx_path/to/smedia/"
...
models.py
from django.contrib.auth.models import User
from reverse_proxy_send_file.storage import ReverseProxySendFileStorageFileSystemStorage
class MyModel(models.Model):
...
user = models.ForeignKey(User, on_delete=models.CASCADE)
my_file = models.FileField(
"My file",
upload_to="my_files/",
storage=ReverseProxySendFileStorageFileSystemStorage(),
)
...
views.py
from django.http import Http404
from reverse_proxy_send_file.views import ReverseProxySendFileView
class ReverseProxySendFileMyFileView(ReverseProxySendFileView):
def check_permission(self, request, resource_url, *args, **kwargs):
obj_qs = MyModel.objects.filter(my_file=resource_url)
if not obj_qs.exists():
raise Http404()
return obj_qs.filter(user=request.user).exists()
urls.py
from django.conf import settings
from views import ReverseProxySendFileMyFileView
urlpatterns = [
...
re_path(
settings.REVERSE_PROXY_SENDFILE_MEDIA_URL + "(?P<resource_url>my_files/.*)$",
views.ReverseProxySendFileMyFileView.as_view(),
name="reverse_proxy_send_file",
),
...
]
- User upload file. The file is stored in
/django_path/to/smedia/my_files/blop.pdf
- User access
/smedia/my_files/blop.pdf
- A django request is performed and it check file access permission for current user (in check_permission).
-
- If the user is allowed return a HTTP response with header :
X-Accel-Redirect=/nginx_path/to/smedia/my_files/blop.pdf
(Nginx will use it to send the file to the client) - If the file os not found return a
404 note found
. - If the user id forbidden, return a
403 response forbidden
- If the user is allowed return a HTTP response with header :
Setup dev environnement
# install dev dependencies
poetry install --no-root
# install git pre-commit
pre-commit install
Run tests
Use tox
command to run all tests on all supported python versions
Examples:
tox
tox -e py38-django40
tox -f py39
Build package and publish on PyPI
Change version number in pyproject.toml
poetry build
poetry publish
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for django_reverse_proxy_send_file-1.0.1.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0f816bd708433d19d07e01b77f7e215ae5845906c917ded112d5bdb7f8e123a2 |
|
MD5 | c682ffb894b6efe99a6b10553905dded |
|
BLAKE2b-256 | edcec978c2815b57c430a06ad151f49a2b4f569d3e0fda02104f5f69b6ffef93 |
Hashes for django_reverse_proxy_send_file-1.0.1-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 33075dcdb35812991f0fc8478c14fb3dba6dddb365c371d86d52a6db492b5444 |
|
MD5 | 45ea2da2b2798c35417f48faddc8be1e |
|
BLAKE2b-256 | 0ab50ef104ce1d98f521accd13f04177bc26fa0e4aa68951c4153a0f568870ae |