views:

102

answers:

2

I want that Apache and Pinax only deliver Attachments to authenticated users.

I found this post, but i can't make it work.

My Apache-conf-file:

WSGIPythonPath /usr/local/bin/python

<VirtualHost *:80>
    ServerName      www.domain.com
    ServerAlias     domain.com


    WSGIDaemonProcess k-production python-path=/path/to/app/pinax-env/lib/python2.6/site-packages
    WSGIProcessGroup k-production

    Alias /site_media  /path/to/app/cp/site_media    
    <Directory /path/to/app/cp/site_media>
    Order deny,allow
    Allow from all
    </Directory>

    WSGIScriptAlias /site_media/media/attachments /path/to/app/cp/deploy/pinax.wsgi
    <Directory /path/to/app/cp/site_media/media/attachments>
    Deny from all
    </Directory>

    XSendFile On
    XSendFileAllowAbove On

    WSGIScriptAlias / /path/to/app/cp/deploy/pinax.wsgi
    <Directory /path/to/app/cp/deploy>
        Order deny,allow
        Allow from all
    </Directory>

</VirtualHost>

and my (still rough) view, that should get called:

@login_required 
def sendfile(request, slug): 

    app, content_object_id, img = slug.split('/')
    project_file = get_object_or_404(Attachment, attachment_file = 'attachments/'+slug) 
    response = HttpResponse() 
    response['X-Sendfile'] =  os.path.join(settings.MEDIA_ROOT,   'attachments/'+slug) 
    content_type = 'application/octet-stream' 
    response['Content-Type'] = content_type 
    response['Content-Disposition'] = 'attachment; filename="%s"' %  os.path.basename(os.path.join(settings.MEDIA_ROOT,   'attachments/'+slug))
    return response

Apache throws a 403 no matter if the user is logged in.

Via the develoment-server i can access the view, but no data will get transmitted.

What is wrong?

+1  A: 

I was trying to do pretty much exactly the same thing, and the solution turned out to be not using WSGIScriptAlias, and instead using a regular Alias to a directory that defined a wsgi handler. For the view I basically just wrote a wrapper around django.views.static.serve.

My apache conf ended up looking like this:

# myproject
<VirtualHost *:8080>
    #DocumentRoot /var/www/myproject/public
    ServerName myproject
    ErrorLog /var/www/myproject/logs/apache_error_log
    CustomLog /var/www/myproject/logs/apache_access_log common

    AliasMatch ^/(media/uploads/protected/.*) /var/www/myproject/src/myproject-trunk/server/django.wsgi/$1
    Alias /media/ /var/www/myproject/public/media/
    Alias / /var/www/myproject/src/myproject-trunk/server/django.wsgi/

    <Directory /var/www/myproject/src/myproject-trunk/server>
        Options ExecCGI
        AddHandler wsgi-script .wsgi
        # WSGIApplicationGroup %{GLOBAL}
        Order allow,deny
        Allow from all
    </Directory>

    <Directory /var/www/myproject/public/media>
        Order deny,allow
        Allow from all
    </Directory>
</VirtualHost>
Josh Ourisman
+1  A: 

Try to concentrate on the development server first - since it is a simpler setup and thus less error prone.

Perhaps try this:

@login_required  def sendfile(request, slug): 
    ## these are never used    
    # app, content_object_id, img = slug.split('/')
    # project_file = get_object_or_404(Attachment, attachment_file = 'attachments/'+slug)

    response = HttpResponse() 
    response['X-Sendfile'] =  os.path.join(settings.MEDIA_ROOT,   'attachments/'+slug)

    import pdb; pdb.set_trace() 
    # your development server will stop here
    # you can now inspect the your context, e.g.
    # >> p response['X-Sendfile']
    # this should print the value of response['X-Sendfile']
    # >> c
    # this will continue program execution
    # for more commands see http://www.python.org/doc/2.4/lib/debugger-commands.html

    content_type = 'application/octet-stream' 
    response['Content-Type'] = content_type 
    # Content-Disposition filename is only for suggesting a name for the file
    # when the user tries to download it, e.g.:
    # response['Content-Disposition'] = 'attachment; filename='localfile.txt'
    response['Content-Disposition'] = 'attachment; filename="%s"' %  os.path.basename(os.path.join(settings.MEDIA_ROOT, 'attachments/'+slug))
    return response


But by using the dev server you won't get any files served, since Apache will do the file serving. You can just ensure, the data sent to apache is correct. Or use (not recommended for your production server)

f = open(os.path.join(settings.MEDIA_ROOT, 'attachments/'+slug), 'rb')
response = HttpResponse(f.read())

instead of

response = HttpResponse() 
response['X-Sendfile'] =  os.path.join(settings.MEDIA_ROOT, 'attachments/'+slug)

Some Links:

Stephan Pötschner
I am asking for my production server setup. that the view get called when running the dev server only proves that urls are correct.
vikingosegundo
This may help, to get your apache setup running:http://serverfault.com/questions/59791/configure-apache-to-handle-a-sub-path-using-wsgi
Stephan Pötschner