def request(params={}, &block)
      # @data has defaults, merge in new params to override
      datum = @data.merge(params)
      datum[:headers] = @data[:headers].merge(datum[:headers] || {})

      validate_params(:request, params, datum[:middlewares])
      # If the user passed in new middleware, we want to validate that the original connection parameters
      # are still valid with the provided middleware.
      if params[:middlewares]
        validate_params(:connection, @data, datum[:middlewares])
      end

      if datum[:user] || datum[:password]
        user, pass = Utils.unescape_uri(datum[:user].to_s), Utils.unescape_uri(datum[:password].to_s)
        datum[:headers]['Authorization'] ||= 'Basic ' + ["#{user}:#{pass}"].pack('m').delete(Excon::CR_NL)
      end

      if datum[:scheme] == UNIX
        datum[:headers]['Host']   ||= ''
      else
        datum[:headers]['Host']   ||= datum[:host] + port_string(datum)
      end

      # if path is empty or doesn't start with '/', insert one
      unless datum[:path][0, 1] == '/'
        datum[:path] = datum[:path].dup.insert(0, '/')
      end

      if block_given?
        Excon.display_warning('Excon requests with a block are deprecated, pass :response_block instead.')
        datum[:response_block] = Proc.new
      end

      datum[:connection] = self

      datum[:stack] = datum[:middlewares].map do |middleware|
        lambda {|stack| middleware.new(stack)}
      end.reverse.inject(self) do |middlewares, middleware|
        middleware.call(middlewares)
      end
      datum = datum[:stack].request_call(datum)

      unless datum[:pipeline]
        datum = response(datum)

        if datum[:persistent]
          if key = datum[:response][:headers].keys.detect {|k| k.casecmp('Connection') == 0 }
            if datum[:response][:headers][key].casecmp('close') == 0
              reset
            end
          end
        else
          reset
        end

        Excon::Response.new(datum[:response])
      else
        datum
      end
    rescue => error
      reset

      # If we didn't get far enough to initialize datum and the middleware stack, just raise
      raise error if !datum

      datum[:error] = error
      if datum[:stack]
        datum[:stack].error_call(datum)
      else
        raise error
      end
    end
def request(params={}, &block)
      # @data has defaults, merge in new params to override
      datum = @data.merge(params)
      datum[:headers] = @data[:headers].merge(datum[:headers] || {})

      validate_params(:request, params, datum[:middlewares])
      # If the user passed in new middleware, we want to validate that the original connection parameters
      # are still valid with the provided middleware.
      if params[:middlewares]
        validate_params(:connection, @data, datum[:middlewares])
      end

      if datum[:user] || datum[:password]
        user, pass = Utils.unescape_uri(datum[:user].to_s), Utils.unescape_uri(datum[:password].to_s)
        datum[:headers]['Authorization'] ||= 'Basic ' + ["#{user}:#{pass}"].pack('m').delete(Excon::CR_NL)
      end

      if datum[:scheme] == UNIX
        datum[:headers]['Host']   ||= ''
      else
        datum[:headers]['Host']   ||= datum[:host] + port_string(datum)
      end

      # if path is empty or doesn't start with '/', insert one
      unless datum[:path][0, 1] == '/'
        datum[:path] = datum[:path].dup.insert(0, '/')
      end

      if block_given?
        Excon.display_warning('Excon requests with a block are deprecated, pass :response_block instead.')
        datum[:response_block] = Proc.new
      end

      datum[:connection] = self

      datum[:stack] = datum[:middlewares].map do |middleware|
        lambda {|stack| middleware.new(stack)}
      end.reverse.inject(self) do |middlewares, middleware|
        middleware.call(middlewares)
      end
      datum = datum[:stack].request_call(datum)

      unless datum[:pipeline]
        datum = response(datum)

        if datum[:persistent]
          if key = datum[:response][:headers].keys.detect {|k| k.casecmp('Connection') == 0 }
            if datum[:response][:headers][key].casecmp('close') == 0
              reset
            end
          end
        else
          reset
        end

        Excon::Response.new(datum[:response])
      else
        datum
      end
    rescue => error
      reset

      # If we didn't get far enough to initialize datum and the middleware stack, just raise
      raise error if !datum

      datum[:error] = error
      if datum[:stack]
        datum[:stack].error_call(datum)
      else
        raise error
      end
    end
Sends the supplied request to the destination host.
   @yield [chunk] @see Response#self.parse
   @param [Hash<Symbol, >] params One or more optional params, override defaults set in Connection.new
     @option params [String] :body text to be sent over a socket
     @option params [Hash<Symbol, String>] :headers The default headers to supply in a request
     @option params [String] :path appears after 'scheme://host:port/'
     @option params [Hash]   :query appended to the 'scheme://host:port/path/' in the form of '?key=value'