diff options
author | Eric Wong <normalperson@yhbt.net> | 2010-07-04 22:16:52 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2010-07-04 22:34:09 +0000 |
commit | 39b178cdebe275cbc8ce19cf269bea7cd15ff4ca (patch) | |
tree | b7628ed278895fcf70ea3206956be586ac9e1ac5 /lib/rainbows/rev/client.rb | |
parent | 75f5aa9a0d6b37a94afbea3121fc2c16e70a2b1d (diff) | |
download | rainbows-39b178cdebe275cbc8ce19cf269bea7cd15ff4ca.tar.gz |
This hopefully allows the "sendfile" gem to be required anywhere in the Rainbows!/Unicorn config file, and not have to be required via RUBYOPT or the '-r' command-line switch. We also modularize HttpResponse and avoids singleton methods in the response path. This (hopefully) makes it easier for individual concurrency models to share code and override individual methods.
Diffstat (limited to 'lib/rainbows/rev/client.rb')
-rw-r--r-- | lib/rainbows/rev/client.rb | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/lib/rainbows/rev/client.rb b/lib/rainbows/rev/client.rb index 8d3a9c9..ababe50 100644 --- a/lib/rainbows/rev/client.rb +++ b/lib/rainbows/rev/client.rb @@ -5,7 +5,9 @@ module Rainbows class Client < ::Rev::IO include Rainbows::EvCore + include Rainbows::HttpResponse G = Rainbows::G + HH = Rack::Utils::HeaderHash def initialize(io) CONN[self] = false @@ -56,6 +58,41 @@ module Rainbows @_write_buffer.empty? && @deferred_bodies.empty? and close.nil? end + def rev_write_response(response, out) + status, headers, body = response + + body.respond_to?(:to_path) or + return write_response(self, response, out) + + headers = HH.new(headers) + io = body_to_io(body) + st = io.stat + + if st.socket? || st.pipe? + do_chunk = !!(headers['Transfer-Encoding'] =~ %r{\Achunked\z}i) + do_chunk = false if headers.delete('X-Rainbows-Autochunk') == 'no' + # too tricky to support keepalive/pipelining when a response can + # take an indeterminate amount of time here. + if out.nil? + do_chunk = false + else + out[0] = CONN_CLOSE + end + + # we only want to attach to the Rev::Loop belonging to the + # main thread in Ruby 1.9 + io = DeferredResponse.new(io, self, do_chunk, body). + attach(Server::LOOP) + elsif st.file? + headers.delete('Transfer-Encoding') + headers['Content-Length'] ||= st.size.to_s + else # char/block device, directory, whatever... nobody cares + return write_response(self, response, out) + end + defer_body(io, out) + write_header(self, response, out) + end + def app_call begin KATO.delete(self) @@ -65,7 +102,7 @@ module Rainbows alive = @hp.keepalive? && G.alive out = [ alive ? CONN_ALIVE : CONN_CLOSE ] if @hp.headers? - DeferredResponse.write(self, response, out) + rev_write_response(response, out) if alive @env.clear @hp.reset |