def process_client(client)
begin
parser = HttpParser.new
params = {}
data = client.readpartial(Const::CHUNK_SIZE)
nparsed = 0
while nparsed < data.length
nparsed = parser.execute(params, data, nparsed)
if parser.finished?
script_name, path_info, handlers = @classifier.resolve(params[Const::REQUEST_URI])
if handlers
params[Const::PATH_INFO] = path_info
params[Const::SCRIPT_NAME] = script_name
params[Const::REMOTE_ADDR] = params[Const::HTTP_X_FORWARDED_FOR] || client.peeraddr.last
request = HttpRequest.new(params, data[nparsed ... data.length] || "", client)
break if request.body == nil
response = HttpResponse.new(client)
handlers.each do |handler|
handler.process(request, response)
break if response.done or client.closed?
end
unless response.done or client.closed?
response.finished
end
else
client.write(Const::ERROR_404_RESPONSE)
end
break
else
data << client.readpartial(Const::CHUNK_SIZE)
if data.length >= Const::MAX_HEADER
raise HttpParserError.new("HEADER is longer than allowed, aborting client early.")
end
end
end
rescue EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::EINVAL,Errno::EBADF
rescue HttpParserError
STDERR.puts "#{Time.now}: BAD CLIENT (#{params[Const::HTTP_X_FORWARDED_FOR] || client.peeraddr.last}): #$!"
rescue => details
STDERR.puts "#{Time.now}: ERROR: #$!"
STDERR.puts details.backtrace.join("\n")
ensure
client.close unless client.closed?
end
end