about summary refs log tree commit homepage
path: root/lib/rainbows/coolio
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2013-02-08 22:45:20 +0000
committerEric Wong <normalperson@yhbt.net>2013-02-11 01:57:05 +0000
commite166cfe5e8d648b544b1291ec157bd234a425e21 (patch)
tree8ac56aadc51d81d4d250cfec696446f19ffd1d64 /lib/rainbows/coolio
parente6faf9e26bcb172026a4984ecadbaa8b6789bcb7 (diff)
downloadrainbows-e166cfe5e8d648b544b1291ec157bd234a425e21.tar.gz
This requires Rack 1.5.x and unicorn 4.6.0 for hijacking
support.  Older versions of Rack continue to work fine,
but we must use unicorn 4.6.0 features to support this.
Diffstat (limited to 'lib/rainbows/coolio')
-rw-r--r--lib/rainbows/coolio/client.rb24
-rw-r--r--lib/rainbows/coolio/thread_client.rb2
2 files changed, 20 insertions, 6 deletions
diff --git a/lib/rainbows/coolio/client.rb b/lib/rainbows/coolio/client.rb
index 8d48bbf..843f574 100644
--- a/lib/rainbows/coolio/client.rb
+++ b/lib/rainbows/coolio/client.rb
@@ -86,6 +86,12 @@ class Rainbows::Coolio::Client < Coolio::IO
     @deferred = true
   end
 
+  def hijacked
+    CONN.delete(self)
+    detach
+    nil
+  end
+
   def write_response_path(status, headers, body, alive)
     io = body_to_io(body)
     st = io.stat
@@ -93,7 +99,8 @@ class Rainbows::Coolio::Client < Coolio::IO
     if st.file?
       defer_file(status, headers, body, alive, io, st)
     elsif st.socket? || st.pipe?
-      chunk = stream_response_headers(status, headers, alive)
+      chunk = stream_response_headers(status, headers, alive, body)
+      return hijacked if nil == chunk
       stream_response_body(body, io, chunk)
     else
       # char or block device... WTF?
@@ -103,10 +110,11 @@ class Rainbows::Coolio::Client < Coolio::IO
 
   def ev_write_response(status, headers, body, alive)
     if body.respond_to?(:to_path)
-      write_response_path(status, headers, body, alive)
+      body = write_response_path(status, headers, body, alive)
     else
-      write_response(status, headers, body, alive)
+      body = write_response(status, headers, body, alive)
     end
+    return hijacked unless body
     return quit unless alive && :close != @state
     @state = :headers
   end
@@ -117,9 +125,11 @@ class Rainbows::Coolio::Client < Coolio::IO
     @env[RACK_INPUT] = input
     @env[REMOTE_ADDR] = @_io.kgio_addr
     @env[ASYNC_CALLBACK] = method(:write_async_response)
+    @hp.hijack_setup(@env, @_io)
     status, headers, body = catch(:async) {
       APP.call(@env.merge!(RACK_DEFAULTS))
     }
+    return hijacked if @hp.hijacked?
 
     (nil == status || -1 == status) ? @deferred = true :
         ev_write_response(status, headers, body, @hp.next?)
@@ -186,12 +196,13 @@ class Rainbows::Coolio::Client < Coolio::IO
     def defer_file(status, headers, body, alive, io, st)
       if r = sendfile_range(status, headers)
         status, headers, range = r
-        write_headers(status, headers, alive)
+        body = write_headers(status, headers, alive, body) or return hijacked
         range and defer_file_stream(range[0], range[1], io, body)
       else
-        write_headers(status, headers, alive)
+        write_headers(status, headers, alive, body) or return hijacked
         defer_file_stream(0, st.size, io, body)
       end
+      body
     end
 
     def stream_file_chunk(sf) # +sf+ is a Rainbows::StreamFile object
@@ -207,8 +218,9 @@ class Rainbows::Coolio::Client < Coolio::IO
     end
   else
     def defer_file(status, headers, body, alive, io, st)
-      write_headers(status, headers, alive)
+      write_headers(status, headers, alive, body) or return hijacked
       defer_file_stream(0, st.size, io, body)
+      body
     end
 
     def stream_file_chunk(body)
diff --git a/lib/rainbows/coolio/thread_client.rb b/lib/rainbows/coolio/thread_client.rb
index abc11d2..ee9fa04 100644
--- a/lib/rainbows/coolio/thread_client.rb
+++ b/lib/rainbows/coolio/thread_client.rb
@@ -14,6 +14,7 @@ class Rainbows::Coolio::ThreadClient < Rainbows::Coolio::Client
 
   # this is only called in the master thread
   def response_write(response)
+    return hijacked if @hp.hijacked?
     ev_write_response(*response, @hp.next?)
     rescue => e
       handle_error(e)
@@ -25,6 +26,7 @@ class Rainbows::Coolio::ThreadClient < Rainbows::Coolio::Client
   def app_response
     begin
       @env[REMOTE_ADDR] = @_io.kgio_addr
+      @hp.hijack_setup(@env, @_io)
       APP.call(@env.merge!(RACK_DEFAULTS))
     rescue => e
       Rainbows::Error.app(e) # we guarantee this does not raise