class Fluent::HttpInput::Handler

def closing?

def closing?
  @next_close
end

def initialize(io, km, callback, body_size_limit, format, log, cors_allow_origins)

def initialize(io, km, callback, body_size_limit, format, log, cors_allow_origins)
  super(io)
  @km = km
  @callback = callback
  @body_size_limit = body_size_limit
  @next_close = false
  @format = format
  @log = log
  @cors_allow_origins = cors_allow_origins
  @idle = 0
  @km.add(self)
  @remote_port, @remote_addr = *Socket.unpack_sockaddr_in(io.getpeername) rescue nil
end

def on_body(chunk)

def on_body(chunk)
  if @body.bytesize + chunk.bytesize > @body_size_limit
    unless closing?
      send_response_and_close("413 Request Entity Too Large", {}, "Too large")
    end
    return
  end
  @body << chunk
end

def on_close

def on_close
  @km.delete(self)
end

def on_connect

def on_connect
  @parser = Http::Parser.new(self)
end

def on_headers_complete(headers)

def on_headers_complete(headers)
  expect = nil
  size = nil
  if @parser.http_version == [1, 1]
    @keep_alive = true
  else
    @keep_alive = false
  end
  @env = {}
  @content_type = ""
  headers.each_pair {|k,v|
    @env["HTTP_#{k.gsub('-','_').upcase}"] = v
    case k
    when /Expect/i
      expect = v
    when /Content-Length/i
      size = v.to_i
    when /Content-Type/i
      @content_type = v
    when /Connection/i
      if v =~ /close/i
        @keep_alive = false
      elsif v =~ /Keep-alive/i
        @keep_alive = true
      end
    when /Origin/i
      @origin  = v
    when /X-Forwarded-For/i
      # For multiple X-Forwarded-For headers. Use first header value.
      v = v.first if v.is_a?(Array)
      @remote_addr = v.split(",").first
    end
  }
  if expect
    if expect == '100-continue'
      if !size || size < @body_size_limit
        send_response_nobody("100 Continue", {})
      else
        send_response_and_close("413 Request Entity Too Large", {}, "Too large")
      end
    else
      send_response_and_close("417 Expectation Failed", {}, "")
    end
  end
end

def on_message_begin

def on_message_begin
  @body = ''
end

def on_message_complete

def on_message_complete
  return if closing?
  # CORS check
  # ==========
  # For every incoming request, we check if we have some CORS
  # restrictions and white listed origins through @cors_allow_origins.
  unless @cors_allow_origins.nil?
    unless @cors_allow_origins.include?(@origin)
      send_response_and_close("403 Forbidden", {'Connection' => 'close'}, "")
      return
    end
  end
  @env['REMOTE_ADDR'] = @remote_addr if @remote_addr
  uri = URI.parse(@parser.request_url)
  params = WEBrick::HTTPUtils.parse_query(uri.query)
  if @format != 'default'
    params[EVENT_RECORD_PARAMETER] = @body
  elsif @content_type =~ /^application\/x-www-form-urlencoded/
    params.update WEBrick::HTTPUtils.parse_query(@body)
  elsif @content_type =~ /^multipart\/form-data; boundary=(.+)/
    boundary = WEBrick::HTTPUtils.dequote($1)
    params.update WEBrick::HTTPUtils.parse_form_data(@body, boundary)
  elsif @content_type =~ /^application\/json/
    params['json'] = @body
  elsif @content_type =~ /^application\/msgpack/
    params['msgpack'] = @body
  end
  path_info = uri.path
  params.merge!(@env)
  @env.clear
  code, header, body = *@callback.call(path_info, params)
  body = body.to_s
  header['Access-Control-Allow-Origin'] = @origin if !@cors_allow_origins.nil? && @cors_allow_origins.include?(@origin)
  if @keep_alive
    header['Connection'] = 'Keep-Alive'
    send_response(code, header, body)
  else
    send_response_and_close(code, header, body)
  end
end

def on_read(data)

def on_read(data)
  @idle = 0
  @parser << data
rescue
  @log.warn "unexpected error", error: $!.to_s
  @log.warn_backtrace
  close
end

def on_write_complete

def on_write_complete
  close if @next_close
end

def send_response(code, header, body)

def send_response(code, header, body)
  header['Content-length'] ||= body.bytesize
  header['Content-type'] ||= 'text/plain'
  data = %[HTTP/1.1 #{code}\r\n]
  header.each_pair {|k,v|
    data << "#{k}: #{v}\r\n"
  }
  data << "\r\n"
  write data
  write body
end

def send_response_and_close(code, header, body)

def send_response_and_close(code, header, body)
  send_response(code, header, body)
  @next_close = true
end

def send_response_nobody(code, header)

def send_response_nobody(code, header)
  data = %[HTTP/1.1 #{code}\r\n]
  header.each_pair {|k,v|
    data << "#{k}: #{v}\r\n"
  }
  data << "\r\n"
  write data
end

def step_idle

def step_idle
  @idle += 1
end