Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Rails 3.1 & 3.2 -- Can't get Sendfile to work #5225

Closed
docwhat opened this Issue Mar 1, 2012 · 9 comments

Comments

Projects
None yet
4 participants
Contributor

docwhat commented Mar 1, 2012

I cannot get the Rack::Sendfile stuff to work with the compiled assets no matter how hard I try. This is with Rails 3.1 and 3.2.1 both.

Steps to reproduce:

ruby -v # => ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-darwin11.3.0]
rails -v # => Rails 3.2.1
rails new myapp
cd myapp/
vim config/environments/production.rb
# I uncomment: config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
env RAILS_ENV=production rake assets:precompile
env RAILS_ENV=production rackup -p 3000
curl -s -o/dev/null -H 'X-Sendfile-Type: X-Sendfile' -D- http://localhost:3000/assets/rails.png

What I expect:

HTTP/1.1 200 OK
...
X-Sendfile: /tmp/myapp/public/assets/rails.png

What I got:

HTTP/1.1 404 Not Found 
Content-Type: text/html; charset=utf-8
Content-Length: 728
X-Request-Id: c42e676c9a8c53cb844c661ad184eb18
X-Runtime: 0.732327
Date: Thu, 01 Mar 2012 06:50:16 GMT
X-Rack-Cache: miss
Server: WEBrick/1.3.1 (Ruby/1.9.2/2011-07-09)
Connection: Keep-Alive

Notes

Tracing down to Rack::Sendfile itself, I see that the response's body does not respond_to? :to_path. The object it has is a bunch of Proxy objects which I don't grok.

I hope this is enough information to figure this out.

Ciao!

Contributor

kennyj commented Mar 1, 2012

I can reproduce it on 3.2.1.
When I added config.serve_static_assets = true, I saw an another response (unexpected normal response).

~$ curl -s -o/dev/null -H 'X-Sendfile-Type: X-Sendfile' -D- http://localhost:3000/assets/rails.png
HTTP/1.1 200 OK
Last-Modified: Thu, 01 Mar 2012 14:51:38 GMT
Content-Type: image/png
Content-Length: 6646
X-Content-Digest: 501d6b0108b930264e19f37cb8ee6c8222d4f30d
Date: Thu, 01 Mar 2012 14:58:13 GMT
Age: 0
X-Rack-Cache: stale, valid, store
Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-02-16)
Connection: Keep-Alive

And when I attempted it with Webrick and Thin, I had same result.

Contributor

homakov commented Mar 1, 2012

Really cannot figure out what seems wrong to you.
Do you have nginx/apache installed? Does it serve files for your rails app?
If yes, than it is problem.
If you use plain rails(and you do, you start server with rackup) why 404 confuses you?
By default rails in env=production does not serve static files. It is duty of server(nginx/apache). If you set serve_static_files = true it does.
Please point out my misunderstanding so I could figure out.

Contributor

kennyj commented Mar 1, 2012

Hi ! @docwhat

And consider, I also think this is not bug.

  1. if you set config.serve_static_assets = false

We expect that files in public directory are served by apache(or nginx). We don't use x_sendfile.

  1. if you set config.serve_static_assets = true

We expect that files in public directory (except assets) are served by ActionDispatch::Static (in action_dispatch/middleware/static.rb),
and files in public/assets directory are served by sprockets.
In any case, we don't use apache(or ngins) and x_sendfile.

In summary, I think that your test had a little mistake.
The following code is demonstaration (properly usage).

$ bundle exec rails g controller Home
$ vim app/controllers/home_controller.rb

def index
  send_file "/path/to/rails.png"
end

~$ curl -s -o/dev/null -H 'X-Sendfile-Type: X-Sendfile' -D- http://localhost:3000/home/
HTTP/1.1 200 OK
Content-Disposition: attachment; filename="rails.png" ★
Content-Transfer-Encoding: binary
Content-Type: image/png
Cache-Control: private
X-UA-Compatible: IE=Edge,chrome=1
Content-Length: 0 ★
X-Sendfile: /home/kennyj/20120301/myapp/public/assets/rails.png ★
X-Request-Id: dbc92ff98fdcd374699e1c1f32cc18dd
X-Runtime: 0.415678
Date: Thu, 01 Mar 2012 16:59:17 GMT
X-Rack-Cache: miss
Connection: keep-alive
Server: thin 1.3.1 codename Triple Espresso
Contributor

kennyj commented Mar 2, 2012

@docwhat what do you think ? :)

Contributor

docwhat commented Mar 2, 2012

I guess I had expectations that didn't match reality.

What I expected is that I could somehow configure Rails/Rack to serve static assets or pre-compiled assets via X-Sendfile.

My use-case is that if I'm running apache (or probably nginex, though I'm not familiar with it) it's easier to just say "Proxy this URL" and nothing else and let rails via X-Sendfile tell apache what it should serve instead of proxying.

Reading the docs certainly didn't make it clear to me or my co-worker (pair programming FTW) that it didn't serve static assets via X-Sendfile.

I would like it if Rails (or maybe Rack, not sure which is the right one) served static assets via X-Sendfile.

Member

drogus commented Mar 3, 2012

We expect that files in public directory are served by apache(or nginx). We don't use x_sendfile.

This does not have to be the case. Sendfile is mostly used when you need to serve only some particular files with apache or nginx. Let's say you have user's private documents that are available only by singing in. You can serve all your public assets by web server (serve_static_assets = false), but still use sendfile to handle the files that are not in public/ directory. [comment irrelevant, misunderstood @kennyj and the issue]

@ghost ghost assigned drogus Mar 3, 2012

Member

drogus commented Mar 3, 2012

@docwhat what is the use case of serving static assets with rails behind a web server such as nginx or apache? even with X-Sendfile it will be slower than just handling that with apache and if you're behind such server anyway, what's the point?

Contributor

docwhat commented Mar 3, 2012

Well,

  1. It was what I expected to happen, based on reading the docs.
  2. I doubt it would be much slower. I'd like to see numbers.
  3. I couldn't get apache RewriteRules to work correctly to serve the static content and the proxied rails app.
  4. It'd be easier to configure -- Just proxy and turn on the X-Sendfile support in apache, then you're done.
  5. Configuring half your app in the web-server and half in rails just makes life difficult. Rails knows where the heck its static assets are, why can't it tell my web-server?

@drogus drogus closed this in 55dd060 Mar 3, 2012

Member

drogus commented Mar 3, 2012

@docwhat I don't think that there is much sense in backporting it to 3.2 as it's not common setup anyway, can you just add this to your production.rb file as a temporary workaround?

config.middleware.delete "Rack::Sendfile"
config.middleware.insert_before "ActionDispatch::Static", "Rack::Sendfile", "X-Sendfile"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment