diff options
author | Eric Wong <normalperson@yhbt.net> | 2010-12-30 08:33:15 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2011-01-04 16:37:42 -0800 |
commit | e21939d776673b2f8887adf7a5c64812b7d2e98e (patch) | |
tree | 48aa3a71201e770758bd09b325c3f2704411af7f /lib/rainbows/process_client.rb | |
parent | 4a76da1833922c74e147be5def9bfe04fd0c16a2 (diff) | |
download | rainbows-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.rb | 43 |
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 |