573: def process_client(client)
574: begin
575: parser = HttpParser.new
576: params = HttpParams.new
577: request = nil
578: data = client.readpartial(Const::CHUNK_SIZE)
579: nparsed = 0
580:
581:
582:
583:
584:
585: while nparsed < data.length
586: nparsed = parser.execute(params, data, nparsed)
587:
588: if parser.finished?
589: if not params[Const::REQUEST_PATH]
590:
591: uri = URI.parse(params[Const::REQUEST_URI])
592: params[Const::REQUEST_PATH] = uri.request_uri
593: end
594:
595: raise "No REQUEST PATH" if not params[Const::REQUEST_PATH]
596:
597: script_name, path_info, handlers = @classifier.resolve(params[Const::REQUEST_PATH])
598:
599: if handlers
600: params[Const::PATH_INFO] = path_info
601: params[Const::SCRIPT_NAME] = script_name
602: params[Const::REMOTE_ADDR] = params[Const::HTTP_X_FORWARDED_FOR] || client.peeraddr.last
603:
604:
605: notifiers = handlers.select { |h| h.request_notify }
606: request = HttpRequest.new(params, client, notifiers)
607:
608:
609: break if request.body == nil
610:
611:
612: response = HttpResponse.new(client)
613:
614:
615: handlers.each do |handler|
616: handler.process(request, response)
617: break if response.done or client.closed?
618: end
619:
620:
621: unless response.done or client.closed?
622: response.finished
623: end
624: else
625:
626: client.write(Const::ERROR_404_RESPONSE)
627: end
628:
629: break
630: else
631:
632: chunk = client.readpartial(Const::CHUNK_SIZE)
633: break if !chunk or chunk.length == 0
634:
635: data << chunk
636: if data.length >= Const::MAX_HEADER
637: raise HttpParserError.new("HEADER is longer than allowed, aborting client early.")
638: end
639: end
640: end
641: rescue EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::EINVAL,Errno::EBADF
642: client.close rescue Object
643: rescue HttpParserError
644: if $mongrel_debug_client
645: STDERR.puts "#{Time.now}: BAD CLIENT (#{params[Const::HTTP_X_FORWARDED_FOR] || client.peeraddr.last}): #$!"
646: STDERR.puts "#{Time.now}: REQUEST DATA: #{data.inspect}\n---\nPARAMS: #{params.inspect}\n---\n"
647: end
648: rescue Errno::EMFILE
649: reap_dead_workers('too many files')
650: rescue Object
651: STDERR.puts "#{Time.now}: ERROR: #$!"
652: STDERR.puts $!.backtrace.join("\n") if $mongrel_debug_client
653: ensure
654: client.close rescue Object
655: request.body.delete if request and request.body.class == Tempfile
656: end
657: end