views:

1668

answers:

1

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?

+6  A: 

For those who may still be wondering, this post is very close to what ended up working.

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:

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.

Rich Apodaca
You are a champion among men, thanks for this.
hornairs
Neat! Simple and straight to the point!
goodwill