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