django-downloadview
django-downloadview copied to clipboard
Document integration of ObjectDownloadView with NGINX acceleration
Currently, there is not an example/documentation for how to integrate ObjectDownloadView
with NGINX XAccelRedirectMiddleware
. This would be a helpful example for new users.
@Natim I'm currently looking into this and will submit a PR if/when I figure it out. Do you have any recommendations for this issue?
Specifically, the type of View
I am trying to accelerate is:
https://github.com/jazzband/django-downloadview/blob/563b2a4f7b354cb930aa7067e6e1341dbb34f5e7/demo/demoproject/object/views.py#L5-L6
https://github.com/jazzband/django-downloadview/blob/563b2a4f7b354cb930aa7067e6e1341dbb34f5e7/demo/demoproject/object/urls.py#L6-L11
As a note, ObjectDownloadView
is listed as supported for acceleration in the docs: https://django-downloadview.readthedocs.io/en/latest/optimizations/index.html#supported-features-grid
@johnthagen Did you manage to get it working?
@amarandon I did not. The challenge I had was that by using object primary keys, I couldn't find a corollary to how to translate those into something to pass NGINX.
I think this would be a very important addition to this library, but after trying for some time I could not figure it out. I do hope that someone is able to and can share their findings with the community.
@Natim Do you have any insights or directions someone could take who is trying to discover how to do this? Is this something that is intended to be supported?
I guess what you are looking for is probably https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/
- https://github.com/jazzband/django-downloadview/blob/45e1219275f9549b60fd8265737171ac450f2161/demo/demoproject/object/views.py
- https://github.com/jazzband/django-downloadview/blob/45e1219275f9549b60fd8265737171ac450f2161/demo/demoproject/nginx/views.py
Basically your ObjectView will return an URL that will be transmitted in a X-Accel header to Nginx which will handle the file.
@Natim So if I understand correctly ObjectDownloadView should add the correct header out of the box and we only need to configure nginx to make use of it? I just had a look in browser's devtools and that doesn't seem to be the case :thinking:
If I understand the code correctly it would work like that if you configure the XAccelMiddleware to monitor the path that your ObjectResponse will use.
@Natim What confuses me is what to put in DOWNLOADVIEW_RULES
and how it relates to Django URLs configuration and Nginx configuration.
I have a Photo
model like this:
class Photo(models.Model):
file = models.ImageField(upload_to='uploads/%Y/%m/%d/')
And an ObjectDownloadView
configured in urls.py
like this:
path('photos/<int:pk>', ObjectDownloadView.as_view(model=Photo), name='photo_file'),
This works as expected: files are served through the Python view.
Now in settings.py
I've added django_downloadview.SmartDownloadMiddleware
at the end of my MIDDLEWARE
lists. I've enabled the nginx backend with DOWNLOADVIEW_BACKEND = "django_downloadview.nginx.XAccelRedirectMiddleware"
but now I'm confused as to how I should configure DOWNLOADVIEW_RULES
. I tried this:
DOWNLOADVIEW_RULES = [
{
'source_url': '/photos/',
'destination_url': '/uploads/',
},
]
Along with this entry in nginx config:
location /uploads/ {
internal;
# /home/myuser/myproject contains a directory named 'uploads' which contains uploaded photos
alias /home/myuser/myproject;
}
But this doesn't seem to change anything. In fact I'm not even sure of how to verify that it works. I was kind of expecting a line in nginx log files saying it did the internal redirection but I'm not sure if this expectation is reasonable.
I think the issue is with
DOWNLOADVIEW_RULES = [
{
'source_url': '/photos/',
'destination_url': '/uploads/',
},
]
can you try:
DOWNLOADVIEW_RULES = ['/uploads']
Disclaimer: I had a very quick look at this thread and I've not been coding with Django for some time now...
I haven't figured out where is the issue at the moment.
I'm not even sure of how to verify that it works
As far as I remember, in order to debug, you can:
- disable X-Accel backend in Django settings and check that files are served. You did that already if I understood well.
- enable X-Accel backend in Django settings but comment /uploads/ section in Nginx configuration, then check HTTP response.
- If response does have X-Accel-Redirect header, then it looks like Nginx didn't catch this header (or the value of the header), so check Nginx configuration.
- If response doesn't have X-Accel-Redirect header, then it looks like the middleware didn't catch the URL as expected. So check Django configuration.
There is also some assert_x_accel_redirect() utility to create tests. It may be useful to check that middleware catches the response and transforms it to X-Accel as expected. See https://django-downloadview.readthedocs.io/en/latest/optimizations/nginx.html#test-responses-with-assert-x-accel-redirect