Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serving Large Files Through Nginx via Rails 2.3 Using x-sendfile

Let's say I have a Rails 2.3.2 application fronted by nginx and served by mongrel in which I need to serve a large static file through Rails (to control access to it). I want the Rails app to delegate the transfer of the file to nginx, to avoid blocking the mongrel instance.

The available information seems contradictory and incomplete. This post shows how to do it with Apache, and hints that it can also be done with ngninx - but no examples. This post and this post show how to do it using the a plugin that apparently Rails 2.3 makes uncessary. This post suggests that maybe there isn't support for x-sendfile with nginx after all.

I'd rather not muck around with plugins for things Rails can now do by itself.

Has anybody gotten x-sendfile-like behavior to work using no plugins and Rails 2.3/nginx/mongrel? If not, what's the best documentation for getting it to work with a plugin (and/or monkeypatch) and Rails 2.3/nginx/mongrel?

like image 791
Rich Apodaca Avatar asked Jun 05 '09 06:06

Rich Apodaca


1 Answers

The main idea: all your controller does is to set the nginx x-accel-redirect header. Once your controller method returns (which will be very fast), nginx will look at the header your Rails app set. If x-accel-redirect is set, then nginx serves the static file.

Your controller will look something like:

def show  
  @attachment = Attachment.find(params[:id])  
  # Do anything else you need for authentication, etc. 

  head(:x_accel_redirect => '/files/' + @attachment.filename,  
   :content_type => @attachment.content_type,  
   :content_disposition => "attachment; filename=\"#{@attachment.filename}\"")  
end  

This alone won't do the trick. You need to also tell nginx about the files located at $RAILS_ROOT/files. Add this to the end of your nginx config inside the server block:

location /files {
  root /path/to/rails_app;  
  internal;  
}

Put the static file into $RAILS_ROOT/files and it should work. No need for plugins or monkeypatching Tested with Rails 2.3.2 and 2.3.14.

like image 104
Rich Apodaca Avatar answered Nov 03 '22 17:11

Rich Apodaca