516: def process_client(client)
517: begin
518: parser = HttpParser.new
519: params = {}
520:
521: data = client.readpartial(Const::CHUNK_SIZE)
522: nparsed = 0
523:
524:
525:
526:
527:
528: while nparsed < data.length
529: nparsed = parser.execute(params, data, nparsed)
530:
531: if parser.finished?
532: script_name, path_info, handlers = @classifier.resolve(params[Const::REQUEST_URI])
533:
534: if handlers
535: params[Const::PATH_INFO] = path_info
536: params[Const::SCRIPT_NAME] = script_name
537: params[Const::REMOTE_ADDR] = params[Const::HTTP_X_FORWARDED_FOR] || client.peeraddr.last
538: data = data[nparsed ... data.length] || ""
539:
540: if handlers[0].request_notify
541:
542: handlers[0].request_begins(params)
543: end
544:
545:
546: request = HttpRequest.new(params, data, client)
547:
548:
549: break if request.body == nil
550:
551:
552: response = HttpResponse.new(client)
553:
554:
555: handlers.each do |handler|
556: handler.process(request, response)
557: break if response.done or client.closed?
558: end
559:
560:
561: unless response.done or client.closed?
562: response.finished
563: end
564: else
565:
566:
567: client.write(Const::ERROR_404_RESPONSE)
568: end
569:
570: break
571: else
572:
573: data << client.readpartial(Const::CHUNK_SIZE)
574: if data.length >= Const::MAX_HEADER
575: raise HttpParserError.new("HEADER is longer than allowed, aborting client early.")
576: end
577: end
578: end
579: rescue EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::EINVAL,Errno::EBADF
580:
581: rescue HttpParserError
582: STDERR.puts "#{Time.now}: BAD CLIENT (#{params[Const::HTTP_X_FORWARDED_FOR] || client.peeraddr.last}): #$!"
583: rescue => details
584: STDERR.puts "#{Time.now}: ERROR: #$!"
585: STDERR.puts details.backtrace.join("\n")
586: ensure
587: client.close unless client.closed?
588: end
589: end