Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serving static files with logic in django (keeping a downloadcount)

I have a site which enables the user to download certain files. However I want to keep a download count for each file so going the usual way by putting the static files on a different subdomain and then letting apache do the heavy lifting is not a way as well as HttpResponseRedirecting the user to a subdomain isn't good because then the user 'sees' the proper download url and can therefore download the file without incrementing the download count. I could just build a view which then serve()s the file however i am worried about that "big fat disclaimer". How would you/did you implement this? I am quite shure I am not the only one with that problem.

About the Platform: I am using apache and mod_wsgi.

Thank you

like image 708
niklasfi Avatar asked Sep 30 '10 22:09

niklasfi


2 Answers

We've implemented a system where we needed to control download access to (largish) static files, naturally not wanting Django to serve them itself. We came up with a scheme whereby the Django app, after validating that the user was allowed to download the file (or increment a counter, in your case) we would create a randomly-named symlink to the file, which Apache had access to (be careful: make sure directory indexing is off etc), and then redirect the user to that symlink to be served by Apache.

We have a "cleanup" cronjob that cleans up symlink a minute after they're created, so if they want to download it again, they have to go through Django and have it counted again. Now, theoretically they could download it more than once in that time, but is that likely to happen? You could clean up more than every minute: Apache just needs the symlink to exist at the beginning of the download, not throughout the whole thing.

I'd be curious to know how others address this problem, as I agree with the OP that it is a common scenario.

like image 130
psj Avatar answered Sep 28 '22 14:09

psj


psj's answer is definitely one viable option. Another option you should investigate is putting a reverse-proxy server in-front of apache like Perlbal which supports "X-REPROXY-URL" headers.

Once you have the reverse-proxy server in place, instead of sending the user a redirect response, you can send a response with the "X-REPROXY-URL" header set to a URL where the proxy server can access but the user can't. The proxy server will then read in the file from the location you sent in the header, and then serve it out to your client. They'll do so in an efficient way and since all your Django app server needs to send is a response with a header set, it is free to handle another request.

like image 23
SeanOC Avatar answered Sep 28 '22 14:09

SeanOC