about summary refs log tree commit homepage
path: root/lib/rainbows/process_client.rb
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2010-12-30 08:33:15 +0000
committerEric Wong <normalperson@yhbt.net>2011-01-04 16:37:42 -0800
commite21939d776673b2f8887adf7a5c64812b7d2e98e (patch)
tree48aa3a71201e770758bd09b325c3f2704411af7f /lib/rainbows/process_client.rb
parent4a76da1833922c74e147be5def9bfe04fd0c16a2 (diff)
downloadrainbows-e21939d776673b2f8887adf7a5c64812b7d2e98e.tar.gz
Rack::Utils::HeaderHash is still very expensive in Rack 1.2,
especially for simple things that we want to run as fast as
possible with minimal interference.  HeaderHash is unnecessary
for most requests that do not send Content-Range in responses.
Diffstat (limited to 'lib/rainbows/process_client.rb')
-rw-r--r--lib/rainbows/process_client.rb43
1 files changed, 15 insertions, 28 deletions
diff --git a/lib/rainbows/process_client.rb b/lib/rainbows/process_client.rb
index 54e59e8..d840778 100644
--- a/lib/rainbows/process_client.rb
+++ b/lib/rainbows/process_client.rb
@@ -1,54 +1,41 @@
 # -*- encoding: binary -*-
-# :enddoc:
-require 'rainbows/rack_input'
 module Rainbows::ProcessClient
-  G = Rainbows::G
   include Rainbows::Response
-  HttpParser = Rainbows::HttpParser
   include Rainbows::RackInput
   include Rainbows::Const
 
-  # once a client is accepted, it is processed in its entirety here
-  # in 3 easy steps: read request, call app, write app response
-  # this is used by synchronous concurrency models
-  #   Base, ThreadSpawn, ThreadPool
-  def process_client(client) # :nodoc:
-    hp = HttpParser.new
-    client.kgio_read!(16384, buf = hp.buf)
-    remote_addr = client.kgio_addr
-    alive = false
+  def process_loop
+    @hp = hp = Rainbows::HttpParser.new
+    kgio_read!(16384, buf = hp.buf) or return
 
     begin # loop
       until env = hp.parse
-        client.timed_read(buf2 ||= "") or return
+        timed_read(buf2 ||= "") or return
         buf << buf2
       end
 
-      set_input(env, hp, client)
-      env[REMOTE_ADDR] = remote_addr
-      status, headers, body = APP.call(env.update(RACK_DEFAULTS))
+      set_input(env, hp)
+      env[REMOTE_ADDR] = kgio_addr
+      status, headers, body = APP.call(env.merge!(RACK_DEFAULTS))
 
       if 100 == status.to_i
-        client.write(EXPECT_100_RESPONSE)
+        write(EXPECT_100_RESPONSE)
         env.delete(HTTP_EXPECT)
         status, headers, body = APP.call(env)
       end
-
-      if hp.headers?
-        headers = HH.new(headers)
-        range = make_range!(env, status, headers) and status = range.shift
-        headers[CONNECTION] = (alive = hp.next?) ? KEEP_ALIVE : CLOSE
-        client.write(response_header(status, headers))
-      end
-      write_body(client, body, range)
+      write_response(status, headers, body, alive = @hp.next?)
     end while alive
   # if we get any error, try to write something back to the client
   # assuming we haven't closed the socket, but don't get hung up
   # if the socket is already closed or broken.  We'll always ensure
   # the socket is closed at the end of this function
   rescue => e
-    Rainbows::Error.write(client, e)
+    handle_error(e)
   ensure
-    client.close unless client.closed?
+    close unless closed?
+  end
+
+  def handle_error(e)
+    Rainbows::Error.write(self, e)
   end
 end