def process_client(client)
begin
parser = HttpParser.new
params = HttpParams.new
request = nil
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_PATH])
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
notifier = handlers[0].request_notify ? handlers[0] : nil
request = HttpRequest.new(params, client, notifier)
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
chunk = client.readpartial(Const::CHUNK_SIZE)
break if !chunk or chunk.length == 0
data << chunk
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
client.close rescue Object
rescue HttpParserError
if $mongrel_debug_client
STDERR.puts "#{Time.now}: BAD CLIENT (#{params[Const::HTTP_X_FORWARDED_FOR] || client.peeraddr.last}): #$!"
STDERR.puts "#{Time.now}: REQUEST DATA: #{data.inspect}\n---\nPARAMS: #{params.inspect}\n---\n"
end
rescue Errno::EMFILE
reap_dead_workers('too many files')
rescue Object
STDERR.puts "#{Time.now}: ERROR: #$!"
STDERR.puts $!.backtrace.join("\n") if $mongrel_debug_client
ensure
client.close rescue Object
request.body.delete if request and request.body.class == Tempfile
end
end