Rainbows! 3.1.0 - minor updates
[rainbows.git] / lib / rainbows / process_client.rb
blobbf6d20bf2be5c73b146129a2691185cacb0d4e4c
1 # -*- encoding: binary -*-
2 # :enddoc:
3 module Rainbows::ProcessClient
4   include Rainbows::Response
5   include Rainbows::Const
7   NULL_IO = Unicorn::HttpRequest::NULL_IO
8   RACK_INPUT = Unicorn::HttpRequest::RACK_INPUT
9   IC = Unicorn::HttpRequest.input_class
11   def process_loop
12     @hp = hp = Rainbows::HttpParser.new
13     kgio_read!(16384, buf = hp.buf) or return
15     begin # loop
16       until env = hp.parse
17         timed_read(buf2 ||= "") or return
18         buf << buf2
19       end
21       set_input(env, hp)
22       env[REMOTE_ADDR] = kgio_addr
23       status, headers, body = APP.call(env.merge!(RACK_DEFAULTS))
25       if 100 == status.to_i
26         write(EXPECT_100_RESPONSE)
27         env.delete(HTTP_EXPECT)
28         status, headers, body = APP.call(env)
29       end
30       write_response(status, headers, body, alive = @hp.next?)
31     end while alive
32   # if we get any error, try to write something back to the client
33   # assuming we haven't closed the socket, but don't get hung up
34   # if the socket is already closed or broken.  We'll always ensure
35   # the socket is closed at the end of this function
36   rescue => e
37     handle_error(e)
38   ensure
39     close unless closed?
40   end
42   def handle_error(e)
43     Rainbows::Error.write(self, e)
44   end
46   def set_input(env, hp)
47     env[RACK_INPUT] = 0 == hp.content_length ? NULL_IO : IC.new(self, hp)
48   end
49 end