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.0.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2889a1ff9de449438ef0aab17d55eb7daa00a9691d3299593d9e4a095afef51a |
|
MD5 | b4856a749b2d074ed0be43b86ccd0dc7 |
|
BLAKE2b-256 | b5a5040127fb2cfce87b70ee1e8e885615d1b4836a26ebecbbc291fcd300cccb |
Hashes for django_reverse_proxy_send_file-1.0.0-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | eb111f82e0c98bc7aac2529716835852e5f4adb4f8948c753940866ad05eb995 |
|
MD5 | 443654294709dac3d5dfbd7947c56d29 |
|
BLAKE2b-256 | 0f9654418ee9daa062ce16b2489392deae62e19d2ae6799ba6150a957ee006f2 |