Forwarding downloads from the dispatcher to the web server

If you have a Rails application which requires for the users to be able to download files, either because you authenticate them, or because you need some pre-processing before serving the file, you will probably use send_file or send_data to send them from your action.

This works quite well when the files are small and/or you do not have too many concurrent requests. If the latter happens, you will end up using too many resources (i.e. too many dispatchers), thus using more RAM, and eventually, swapping too much.

The solution I'm bringing to you today, is something I have recently started using in in.solit.us. Basically, this method will use the X-Sendfile header to forward the download requests to your web server (either Lighty or Apache2).

This feature is already supported by default in Lighty. You may want to take a look at the following article in Lighttpd's blog: mod_proxy_core got X-Sendfile Support.

Setting this up in Apache2 is not so easy, and requires using mod_xsendfile, written by Nils Maier, licensed under the Apache License.

First of all, we need to compile mod_xsendfile for our Apache installation.

Download the module from mod_xsendfile page:
persefone:~# wget http://celebnamer.celebworld.ws/stuff/mod_xsendfile/mod_xsendfile.c

You will need apxs2 for this, so if executing apxs2 gives you a command not found, you will need to install the Apache development headers.

If you are using the default Apache2-MPM-Prefork issue the following command:
persefone:~# apt-get install apache2-prefork-dev

Otherwise (MPM-Worker) install the threaded development headers,
persefone:~# apt-get install apache2-threaded-dev

At this point, you can compile the module using the following command. A line in httpd.conf enabling the module will be automatically added.
persefone:~# apxs2 -cia mod_xsendfile.c
...
[activating module `xsendfile' in /etc/apache2/httpd.conf]


You need to activate now the module for the directory you want to use it. You can do it either in /etc/apache2/sites-enabled/ or in an .htaccess file in the directory.

If we wanted to enable /var/www/downloadable_files/, we will need the following:
<Directory /var/www/downloadable_files>
   
...
    XSendFile on
   
XSendFileAllowAbove on (If set to ON, the module will allow to send files above the specified directory).
</Directory>

Now, the Rails goodies:

#Check if file exists and maybe authenticate?
if File::exist? "#{@path}/#{@archive.url}"
    #send_file("#{@path}/#{@archive.url}",
    #                  :filename => @archive.original_name)  

    #The code below equals the send_file function above.
    response.headers['Content-Type'] = "application/force-download"
    response.headers['Content-Disposition'] = "attachment; filename=\"#{@archive.original_name}\""
    response.headers["X-Sendfile"] = "#{@path}/#{@archive.url}"
    response.headers['Content-length'] = @archive.length
    render :nothing => true
      
end

The code explains for itself. In Content-Disposition we will set under filename the name we want the file to appear to the user who downloads it, and we have to supply the X-Sendfile header with the path+name of the file.

The last command (render :nothing => true) tells Rails not to render anything. If Rails renders something, Apache2 will not get the X-Sendfile request.



 


Trackback

Trackback URL for this entry:
http://www.gra2.com/trackback.php/forward-downloads-dispatcher-to-server

No trackback comments for this entry.

Comments

Post a comment

jsDsMf fgoG62mvVof47J1fCaLkg

Anonymous on Thursday, July 23 2009 @ 03:14 PM CEST Reply | #

Search



About

newton.gra2.com is a blog about technology, opinion and random thoughts written by Daniel Alvarez, a computer engineer currently living in Zurich, Switzerland.

Topics

News (20/0)
Manuals (24/0)
Security (7/0)
Music (3/0)
Weeklog (1/0)
Personal (34/0)
Photos (3/0)
Opinion (14/0)
Windows (5/0)

Blogroll

Pros i contres (Jordi)
Entrepa de fusta (Oriol)
Spaghetti Code (Isaac)
Made in net (Eric)
Nogare (Juan)
Blog de Isaac Jimenez
Web d'en Jaume Benet
Montcada Wireless (Fran)
Blog d'en Ricard Forniol
Angela Fabregues
in.solit.us

Libertad Digital
FOX News
The Wall Street Journal
The Washington Times
The Jerusalem Post

Michelle Malkin
Eurabian News
Nihil Obstat
Barcepundit
Expose the left
Davids Medienkritik
Johan Norberg
Ayaan Hirsi Ali

User Functions

:

:


Lost your password?

Latest posts

Stories

No new stories

Comments last 2 days

No new comments

Trackbacks last 2 days

No new trackback comments

Links last 2 weeks

No recent new links