XsendFile with apache and django
Asked Answered
I

2

7

I have my django served by apache using Vhost. The conf file is the following

WSGIPythonPath /srv/www/myproject/testproject/


<VirtualHost *:80>
    ServerAdmin [email protected]
    ServerName www.betarhombus.com
    WSGIScriptAlias / /srv/www/testproject/testproject/testproject/wsgi.py
    <Directory /srv/www/testproject/testproject/testproject>
        <Files wsgi.py>
            Require all granted
        </Files>
    </Directory>
    Alias /static/ /srv/www/testproject/testproject/static/
    Alias /media/  /srv/www/testproject/testproject/media/

    <Directory /srv/www/testproject/testproject/static>
        Require all granted
    </Directory>
    <Directory /srv/www/testproject/testproject/media>
        Require all granted
    </Directory>

</VirtualHost>

I want to restrict media files to being served only on speicific logged users. So I ran into XsendFile. If I understand it correctly what it does is while you have django do all the checking for the media file you want to serve it is then served by Apache as static file. So the procedure is the follwing if I am guessing right

  1. Activate XsendFile.
  2. Create view that checks for media files permissions etc and serves them
  3. associate with url in urls.py file

Then I can use ` and will work normally like if it was served by using the initial media file url. Do I understand it correctly? My questions are the following:

About 1.activating XSendFile. Should this be done in conf file inside my Vhost tag? Is setting XsendFile on enough? Should I remove the Alias for media directive and also the section for the media files? I want media files only to be served by my view?

Is there anything else that I should be aware of?

Edit: My setup is

 <VirtualHost *:80>
    ServerAdmin [email protected]
    ServerName www.betarhombus.com
    WSGIScriptAlias / /srv/www/testproject/testproject/testproject/wsgi.py
    XSendFile On
    XsendFilePath /srv/www/testproject/testproject/media/
    <Directory /srv/www/testproject/testproject/testproject>
        <Files wsgi.py>
            Require all granted
        </Files>
    </Directory>
    Alias /static/ /srv/www/testproject/testproject/static/
    <Directory /srv/www/testproject/testproject/static>
        Require all granted
    </Directory>
</VirtualHost>

my urls.py

#for xsendmedia file serving
url(r'^media\/(?P<path>.*)$', 'customer.views.media_xsendfile'),

and my view

def media_xsendfile(request, path):  
    #here will be checked if user can access media
    response = HttpResponse()
    response['Content-Type']=''
    response['X-Sendfile']= smart_str(os.path.join(settings.MEDIA_ROOT, path))
    return response

My problem is that some of the media files are shared normally and some are not, and get an Internal Server Error

Isherwood answered 8/7, 2014 at 12:12 Comment(1)
What do you mean by some of the media files are shared normally and some are not? Could you explain it a little more? Are you using the staff_member_required decorator?Bib
B
5

Also make sure to set the XSendFilePath in your Apache configuration file like so,

XSendFile on
XSendFilePath "//path/to/files/on/disk"
<Directory "//path/to/files/on/disk">
    Order Deny,Allow
    Allow from all
</Directory>

and include this in your view while returning the response:

response['X-Sendfile'] = smart_str(file_path)

And to answer your questions:

  • Activate the XSendFile in the vhost tag
  • I've written above what else needs to be done in the view
  • I'm not sure if you should remove the media alias, the log files should tell you if having them is a problem
Bib answered 8/7, 2014 at 12:20 Comment(3)
What should I set as value of the XSendFilePath?If I leave the Alias for media won't users be able to access media files if by entering the path in the url? e.g www.mydomain.com/media/path_to_mediafileIsherwood
I don't think that's a possibility unless you have the /media url in your urls.py. I've updated the answer above to answer your question.Bib
If I was of any help please accept my answer, or answer the question with your solution please. Thanks!Bib
L
1

If anyone is facing same issue with a newer version of Apache (2.4), here's how I finally manage to make it worked :

<VirtualHost *:80>
        XSendFile on
        
        Alias /static/ /mnt/mysite/static/
        Alias /media/ /mnt/mysite/media/

        <Directory /mnt/mysite/static>
                Require all granted
        </Directory>

        <Directory /mnt/mysite/media>
                Require all granted
        </Directory>

        <Directory /mnt/mysite/media/protected>
                Require all denied
        </Directory>
        XSendFilePath /mnt/mysite/media/protected

        <Directory /home/benbb96/mysite>
                <Files wsgi.py>
                        Require all granted
                </Files>
        </Directory>

        WSGIDaemonProcess mysite python-home=/home/benbb96/mysite/venv python-path=/home/benbb96/mysite/
        WSGIScriptAlias / /home/benbb96/mysite/config/wsgi.py
</VirtualHost>

I run my site with wsgi in deamon mode (cf. docs) and I wanted to protect some media files which are uploaded in protected/. So I added a <Directory> directive to block access to it and then I use XSendFile in my view, which also verify if user has access to the file, to serve the protected file.

Note that my static and media files are hosted on a mounted folder from the network (/mnt/) but that doesn't cause any issues.

Laurice answered 18/12, 2020 at 11:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.