# File lib/right_http_connection.rb, line 319
    def request(request_params, &block)
      # We save the offset here so that if we need to retry, we can return the file pointer to its initial position
      mypos = get_fileptr_offset(request_params)
      loop do
        # if we are inside a delay between retries: no requests this time!
        if error_count > @params[:http_connection_retry_count] &&
            error_time + @params[:http_connection_retry_delay] > Time.now
          # store the message (otherwise it will be lost after error_reset and
          # we will raise an exception with an empty text)
          banana_message_text = banana_message
          @logger.warn("#{err_header} re-raising same error: #{banana_message_text} " +
                           "-- error count: #{error_count}, error age: #{Time.now.to_i - error_time.to_i}")
          exception = get_param(:exception) || RuntimeError
          raise exception.new(banana_message_text)
        end

        # try to connect server(if connection does not exist) and get response data
        begin
          request_params[:protocol] ||= (request_params[:port] == 443 ? 'https' : 'http')

          request                   = request_params[:request]
          request['User-Agent']     = get_param(:user_agent) || ''

          # (re)open connection to server if none exists or params has changed
          unless @http &&
              @http.started? &&
              @server == request_params[:server] &&
              @port == request_params[:port] &&
              @protocol == request_params[:protocol]
            start(request_params)
          end

          # Detect if the body is a streamable object like a file or socket.  If so, stream that
          # bad boy.
          setup_streaming(request)
          response = @http.request(request, &block)

          error_reset
          eof_reset
          return response

          # We treat EOF errors and the timeout/network errors differently.  Both
          # are tracked in different statistics blocks.  Note below that EOF
          # errors will sleep for a certain (exponentially increasing) period.
          # Other errors don't sleep because there is already an inherent delay
          # in them; connect and read timeouts (for example) have already
          # 'slept'.  It is still not clear which way we should treat errors
          # like RST and resolution failures.  For now, there is no additional
          # delay for these errors although this may change in the future.

          # EOFError means the server closed the connection on us.
        rescue EOFError => e
          @logger.debug("#{err_header} server #{@server} closed connection")
          @http = nil

          # if we have waited long enough - raise an exception...
          if raise_on_eof_exception?
            exception = get_param(:exception) || RuntimeError
            @logger.warn("#{err_header} raising #{exception} due to permanent EOF being received from #{@server}, error age: #{Time.now.to_i - eof_time.to_i}")
            raise exception.new("Permanent EOF is being received from #{@server}.")
          else
            # ... else just sleep a bit before new retry
            sleep(add_eof)
            # We will be retrying the request, so reset the file pointer
            reset_fileptr_offset(request, mypos)
          end
        rescue Exception => e # See comment at bottom for the list of errors seen...
          @http = nil
          # if ctrl+c is pressed - we have to reraise exception to terminate proggy
          if e.is_a?(Interrupt) && !(e.is_a?(Errno::ETIMEDOUT) || e.is_a?(Timeout::Error))
            @logger.debug("#{err_header} request to server #{@server} interrupted by ctrl-c")
            raise
          elsif e.is_a?(ArgumentError) && e.message.include?('wrong number of arguments (5 for 4)')
            # seems our net_fix patch was overriden...
            exception = get_param(:exception) || RuntimeError
            raise exception.new('incompatible Net::HTTP monkey-patch')
          end
          # oops - we got a banana: log it
          error_add(e.message)
          @logger.warn("#{err_header} request failure count: #{error_count}, exception: #{e.inspect}")

          # We will be retrying the request, so reset the file pointer
          reset_fileptr_offset(request, mypos)

        end
      end
    end