about summary refs log tree commit homepage
path: root/lib/rainbows/rev
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2010-07-04 22:16:52 +0000
committerEric Wong <normalperson@yhbt.net>2010-07-04 22:34:09 +0000
commit39b178cdebe275cbc8ce19cf269bea7cd15ff4ca (patch)
treeb7628ed278895fcf70ea3206956be586ac9e1ac5 /lib/rainbows/rev
parent75f5aa9a0d6b37a94afbea3121fc2c16e70a2b1d (diff)
downloadrainbows-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')
-rw-r--r--lib/rainbows/rev/client.rb39
-rw-r--r--lib/rainbows/rev/core.rb1
-rw-r--r--lib/rainbows/rev/deferred_response.rb38
-rw-r--r--lib/rainbows/rev/thread.rb2
4 files changed, 40 insertions, 40 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
diff --git a/lib/rainbows/rev/core.rb b/lib/rainbows/rev/core.rb
index 122d8f4..7457f12 100644
--- a/lib/rainbows/rev/core.rb
+++ b/lib/rainbows/rev/core.rb
@@ -22,6 +22,7 @@ module Rainbows
       # for connections and doesn't die until the parent dies (or is
       # given a INT, QUIT, or TERM signal)
       def worker_loop(worker)
+        Rainbows::HttpResponse.setup(Rainbows::Rev::Client)
         init_worker_process(worker)
         mod = self.class.const_get(@use)
         rloop = Server.const_set(:LOOP, ::Rev::Loop.default)
diff --git a/lib/rainbows/rev/deferred_response.rb b/lib/rainbows/rev/deferred_response.rb
index 63af6b4..f710b5b 100644
--- a/lib/rainbows/rev/deferred_response.rb
+++ b/lib/rainbows/rev/deferred_response.rb
@@ -6,44 +6,6 @@ module Rainbows
     # or proxying IO-derived objects
     class DeferredResponse < ::Rev::IO
       include Rainbows::Const
-      G = Rainbows::G
-      HH = Rack::Utils::HeaderHash
-
-      def self.write(client, response, out)
-        status, headers, body = response
-
-        body.respond_to?(:to_path) or
-            return HttpResponse.write(client, response, out)
-
-        headers = HH.new(headers)
-        io = Rainbows.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 = new(io, client, 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 HttpResponse.write(client, response, out)
-        end
-        client.defer_body(io, out)
-        out.nil? or
-          client.write(HttpResponse.header_string(status, headers, out))
-      end
-
       def initialize(io, client, do_chunk, body)
         super(io)
         @client, @do_chunk, @body = client, do_chunk, body
diff --git a/lib/rainbows/rev/thread.rb b/lib/rainbows/rev/thread.rb
index 387740c..ba80bb1 100644
--- a/lib/rainbows/rev/thread.rb
+++ b/lib/rainbows/rev/thread.rb
@@ -22,7 +22,7 @@ module Rainbows
         enable
         alive = @hp.keepalive? && G.alive
         out = [ alive ? CONN_ALIVE : CONN_CLOSE ] if @hp.headers?
-        DeferredResponse.write(self, response, out)
+        rev_write_response(response, out)
         return quit unless alive && G.alive
 
         @env.clear