class Puma::Client
def setup_body
def setup_body @body_read_start = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond) if @env[HTTP_EXPECT] == CONTINUE # TODO allow a hook here to check the headers before # going forward @io << HTTP_11_100 @io.flush end @read_header = false body = @parser.body te = @env[TRANSFER_ENCODING2] if te te_lwr = te.downcase if te.include? ',' te_ary = te_lwr.split ',' te_count = te_ary.count CHUNKED te_valid = te_ary[0..-2].all? { |e| ALLOWED_TRANSFER_ENCODING.include? e } if te_ary.last == CHUNKED && te_count == 1 && te_valid @env.delete TRANSFER_ENCODING2 return setup_chunked_body body elsif te_count >= 1 raise HttpParserError , "#{TE_ERR_MSG}, multiple chunked: '#{te}'" elsif !te_valid raise HttpParserError501, "#{TE_ERR_MSG}, unknown value: '#{te}'" end elsif te_lwr == CHUNKED @env.delete TRANSFER_ENCODING2 return setup_chunked_body body elsif ALLOWED_TRANSFER_ENCODING.include? te_lwr raise HttpParserError , "#{TE_ERR_MSG}, single value must be chunked: '#{te}'" else raise HttpParserError501 , "#{TE_ERR_MSG}, unknown value: '#{te}'" end end @chunked_body = false cl = @env[CONTENT_LENGTH] if cl # cannot contain characters that are not \d, or be empty if CONTENT_LENGTH_VALUE_INVALID.match?(cl) || cl.empty? raise HttpParserError, "Invalid Content-Length: #{cl.inspect}" end else @buffer = body.empty? ? nil : body @body = EmptyBody set_ready return true end remain = cl.to_i - body.bytesize if remain <= 0 @body = StringIO.new(body) @buffer = nil set_ready return true end if remain > MAX_BODY @body = Tempfile.new(Const::PUMA_TMP_BASE) @body.unlink @body.binmode @tempfile = @body else # The body[0,0] trick is to get an empty string in the same # encoding as body. @body = StringIO.new body[0,0] end @body.write body @body_remain = remain false end