1 # -*- encoding: binary -*-
3 # base module for evented models like Rev and EventMachine
4 module Rainbows::EvCore
5 include Rainbows::Const
6 include Rainbows::Response
8 NULL_IO = Unicorn::HttpRequest::NULL_IO
9 HttpParser = Unicorn::HttpParser
10 autoload :CapInput, 'rainbows/ev_core/cap_input'
12 # Apps may return this Rack response: AsyncResponse = [ -1, {}, [] ]
13 ASYNC_CALLBACK = "async.callback".freeze
15 ASYNC_CLOSE = "async.close".freeze
21 @state = :headers # [ :body [ :trailers ] ] :app_call :close
24 # graceful exit, like SIGQUIT
33 msg = Rainbows::Error.response(e) and write(msg)
38 # returns whether to enable response chunking for autochunk models
39 def stream_response_headers(status, headers)
40 if headers['Content-Length']
43 rv = !!(headers['Transfer-Encoding'] =~ %r{\Achunked\z}i)
44 rv = false if headers.delete('X-Rainbows-Autochunk') == 'no'
46 write(response_header(status, headers))
50 def prepare_request_body
51 # since we don't do streaming input, we have no choice but
52 # to take over 100-continue handling from the Rack application
53 if @env[HTTP_EXPECT] =~ /\A100-continue\z/i
54 write(EXPECT_100_RESPONSE)
55 @env.delete(HTTP_EXPECT)
58 @hp.filter_body(@buf2 = "", @buf)
63 # TeeInput doesn't map too well to this right now...
68 @hp.parse or return want_more
70 if 0 == @hp.content_length
72 app_call # common case
86 @hp.filter_body(@buf2, @buf << data)
91 if @hp.trailers(@env, @buf << data)
103 write(Rainbows::Const::ERROR_413_RESPONSE)
105 # zip back up the stack
106 raise IOError, msg, []
109 MAX_BODY = Unicorn::Const::MAX_BODY
110 TmpIO = Unicorn::TmpIO
112 max = Rainbows.max_bytes
113 len = @hp.content_length
115 if max && (len > max)
116 err_413("Content-Length too big: #{len} > #{max}")
118 len <= MAX_BODY ? StringIO.new("") : TmpIO.new
120 max ? CapInput.new(TmpIO.new, self) : TmpIO.new