1 # -*- encoding: binary -*-
5 # base module for evented models like Rev and EventMachine
8 include Rainbows::Const
11 # Apps may return this Rack response: AsyncResponse = [ -1, {}, [] ]
12 ASYNC_CALLBACK = "async.callback".freeze
14 ASYNC_CLOSE = "async.close".freeze
17 @remote_addr = Rainbows.addr(@_io)
20 @state = :headers # [ :body [ :trailers ] ] :app_call :close
24 # graceful exit, like SIGQUIT
30 msg = Error.response(e) and write(msg)
35 # TeeInput doesn't map too well to this right now...
39 @hp.headers(@env, @buf << data) or return
41 len = @hp.content_length
43 @input = HttpRequest::NULL_IO
44 app_call # common case
46 # since we don't do streaming input, we have no choice but
47 # to take over 100-continue handling from the Rack application
48 if @env[HTTP_EXPECT] =~ /\A100-continue\z/i
49 write(EXPECT_100_RESPONSE)
50 @env.delete(HTTP_EXPECT)
52 @input = CapInput.new(len, self)
53 @hp.filter_body(@buf2 = "", @buf)
62 @hp.filter_body(@buf2, @buf << data)
67 if @hp.trailers(@env, @buf << data)
76 class CapInput < Struct.new(:io, :client, :bytes_left)
77 MAX_BODY = Unicorn::Const::MAX_BODY
80 def self.err(client, msg)
81 client.write(Const::ERROR_413_RESPONSE)
84 # zip back up the stack
85 raise IOError, msg, []
88 def self.new(len, client)
89 max = Rainbows.max_bytes
92 err(client, "Content-Length too big: #{len} > #{max}")
94 len <= MAX_BODY ? StringIO.new("") : Util.tmpio
96 max ? super(Util.tmpio, client, max) : Util.tmpio
101 if (self.bytes_left -= buf.size) < 0
103 CapInput.err(client, "chunked request body too big")
108 def gets; io.gets; end
109 def each(&block); io.each(&block); end
110 def size; io.size; end
111 def rewind; io.rewind; end
112 def read(*args); io.read(*args); end