summary refs log tree commit homepage
path: root/lib
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2010-06-06 02:14:58 +0000
committerEric Wong <normalperson@yhbt.net>2010-06-06 02:14:58 +0000
commitb1315983056f91467b336aeb426759debc006a4e (patch)
tree8a0d3dee51038b567dcb72bd4af40d5ff707da9d /lib
parent6ada0eb9916bbcebbcf2af843c1f5fb11904caee (diff)
centralize body => IO conversion logic
Since EventMachine and Rev shared the same logic for optimizing
and avoiding extra file opens for IO/File-ish response bodies,
so centralize that.

For Ruby 1.9 users, we've also enabled this logic so ThreadPool,
ThreadSpawn, WriterThreadPool, and WriterThreadSpawn can take
advantage of Rainbows::DevFdResponse-generated bodies while
proxying sockets.
Diffstat (limited to 'lib')
-rw-r--r--lib/rainbows.rb15
-rw-r--r--lib/rainbows/base.rb3
-rw-r--r--lib/rainbows/event_machine.rb9
-rw-r--r--lib/rainbows/rev/deferred_response.rb7
4 files changed, 20 insertions, 14 deletions
diff --git a/lib/rainbows.rb b/lib/rainbows.rb
index e186549..5aae746 100644
--- a/lib/rainbows.rb
+++ b/lib/rainbows.rb
@@ -156,6 +156,21 @@ module Rainbows
   # :startdoc:
   autoload :Fiber, 'rainbows/fiber' # core class
 
+  # to_io is not part of the Rack spec, but make an exception here
+  # since we can conserve path lookups and file descriptors
+  # \Rainbows! will never get here without checking for the existence
+  # of body.to_path first.
+  def self.body_to_io(body)
+    if body.respond_to?(:to_io)
+      body.to_io
+    else
+      # try to take advantage of Rainbows::DevFdResponse, calling File.open
+      # is a last resort
+      path = body.to_path
+      path =~ %r{\A/dev/fd/(\d+)\z} ? IO.new($1.to_i) : File.open(path, 'rb')
+    end
+  end
+
 end
 
 # inject the Rainbows! method into Unicorn::Configurator
diff --git a/lib/rainbows/base.rb b/lib/rainbows/base.rb
index a773722..8e5031f 100644
--- a/lib/rainbows/base.rb
+++ b/lib/rainbows/base.rb
@@ -33,8 +33,7 @@ module Rainbows
     if IO.respond_to?(:copy_stream)
       def write_body(client, body)
         if body.respond_to?(:to_path)
-          io = body.respond_to?(:to_io) ? body.to_io : body.to_path
-          IO.copy_stream(io, client)
+          IO.copy_stream(Rainbows.body_to_io(body), client)
         else
           body.each { |chunk| client.write(chunk) }
         end
diff --git a/lib/rainbows/event_machine.rb b/lib/rainbows/event_machine.rb
index b19bdec..12d9e5e 100644
--- a/lib/rainbows/event_machine.rb
+++ b/lib/rainbows/event_machine.rb
@@ -112,18 +112,15 @@ module Rainbows
         end
 
         headers = Rack::Utils::HeaderHash.new(response[1])
-        path = body.to_path
-        io = body.to_io if body.respond_to?(:to_io)
-        io ||= IO.new($1.to_i) if path =~ %r{\A/dev/fd/(\d+)\z}
-        io ||= File.open(path, 'rb') # could be a named pipe
-
+        io = Rainbows.body_to_io(body)
         st = io.stat
+
         if st.file?
           headers.delete('Transfer-Encoding')
           headers['Content-Length'] ||= st.size.to_s
           response = [ response.first, headers.to_hash, [] ]
           HttpResponse.write(self, response, out)
-          stream = stream_file_data(path)
+          stream = stream_file_data(body.to_path)
           stream.callback { quit } unless alive
         elsif st.socket? || st.pipe?
           do_chunk = !!(headers['Transfer-Encoding'] =~ %r{\Achunked\z}i)
diff --git a/lib/rainbows/rev/deferred_response.rb b/lib/rainbows/rev/deferred_response.rb
index dd7a229..62a308c 100644
--- a/lib/rainbows/rev/deferred_response.rb
+++ b/lib/rainbows/rev/deferred_response.rb
@@ -17,12 +17,7 @@ module Rainbows
             return HttpResponse.write(client, response, out)
 
         headers = HH.new(headers)
-
-        # to_io is not part of the Rack spec, but make an exception
-        # here since we can't get here without checking to_path first
-        io = body.to_io if body.respond_to?(:to_io)
-        io ||= ::IO.new($1.to_i) if body.to_path =~ %r{\A/dev/fd/(\d+)\z}
-        io ||= File.open(body.to_path, 'rb')
+        io = Rainbows.body_to_io(body)
         st = io.stat
 
         if st.socket? || st.pipe?