Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

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

Closed
docwhat opened this Issue · 9 comments

4 participants

@docwhat

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!

@kennyj
Collaborator

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.

@homakov

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.

@kennyj
Collaborator

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.

2) 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
@kennyj
Collaborator

@docwhat what do you think ? :)

@docwhat

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.

@drogus
Collaborator

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]

@drogus drogus was assigned
@drogus
Collaborator

@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?

@docwhat

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 issue from a commit
@drogus drogus Handle files from ActionDispatch::Static with Rack::Sendfile (fixes #…
…5225)

This makes rails behave properly when you serve static assets
and you have X-Sendfile headers enabled. Nevertheless in most
cases you should not rely on that and serve static assets with
a webserver like Apache or Nginx (as you already have it in
place anyway if you use X-Sendfile)
55dd060
@drogus drogus closed this in 55dd060
@drogus
Collaborator

@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"
@joshuap joshuap referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.
@andhapp andhapp referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.
@andhapp andhapp referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.