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?
if not params[Const::REQUEST_PATH]
uri = URI.parse(params[Const::REQUEST_URI])
params[Const::REQUEST_PATH] = uri.request_uri
end
raise "No REQUEST PATH" if not params[Const::REQUEST_PATH]
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
notifiers = handlers.select { |h| h.request_notify }
request = HttpRequest.new(params, client, notifiers)
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