def request(verb, path, data = {}, headers = {})
      # Build the URI and request object from the given information
      uri = build_uri(verb, path, data)
      request = class_for_request(verb).new(uri.request_uri)
      if uri.userinfo()
        request.basic_auth uri.user, uri.password
      end

      if proxy_address and uri.scheme.downcase == "https"
        raise SecurityError, "no direct https connection to vault"
      end

      # Get a list of headers
      headers = DEFAULT_HEADERS.merge(headers)

      # Add the Vault token header - users could still override this on a
      # per-request basis
      if !token.nil?
        headers[TOKEN_HEADER] ||= token
      end

      # Add headers
      headers.each do |key, value|
        request.add_field(key, value)
      end

      # Setup PATCH/POST/PUT
      if [:patch, :post, :put].include?(verb)
        if data.respond_to?(:read)
          request.content_length = data.size
          request.body_stream = data
        elsif data.is_a?(Hash)
          request.form_data = data
        else
          request.body = data
        end
      end

      begin
        # Create a connection using the block form, which will ensure the socket
        # is properly closed in the event of an error.
        response = pool.request(uri, request)

        case response
        when Net::HTTPRedirection
          # On a redirect of a GET or HEAD request, the URL already contains
          # the data as query string parameters.
          if [:head, :get].include?(verb)
            data = {}
          end
          request(verb, response[LOCATION_HEADER], data, headers)
        when Net::HTTPSuccess
          success(response)
        else
          error(response)
        end
      rescue *RESCUED_EXCEPTIONS => e
        raise HTTPConnectionError.new(address, e)
      end
    end
def request(verb, path, data = {}, headers = {})
      # Build the URI and request object from the given information
      uri = build_uri(verb, path, data)
      request = class_for_request(verb).new(uri.request_uri)
      if uri.userinfo()
        request.basic_auth uri.user, uri.password
      end

      if proxy_address and uri.scheme.downcase == "https"
        raise SecurityError, "no direct https connection to vault"
      end

      # Get a list of headers
      headers = DEFAULT_HEADERS.merge(headers)

      # Add the Vault token header - users could still override this on a
      # per-request basis
      if !token.nil?
        headers[TOKEN_HEADER] ||= token
      end

      # Add headers
      headers.each do |key, value|
        request.add_field(key, value)
      end

      # Setup PATCH/POST/PUT
      if [:patch, :post, :put].include?(verb)
        if data.respond_to?(:read)
          request.content_length = data.size
          request.body_stream = data
        elsif data.is_a?(Hash)
          request.form_data = data
        else
          request.body = data
        end
      end

      begin
        # Create a connection using the block form, which will ensure the socket
        # is properly closed in the event of an error.
        response = pool.request(uri, request)

        case response
        when Net::HTTPRedirection
          # On a redirect of a GET or HEAD request, the URL already contains
          # the data as query string parameters.
          if [:head, :get].include?(verb)
            data = {}
          end
          request(verb, response[LOCATION_HEADER], data, headers)
        when Net::HTTPSuccess
          success(response)
        else
          error(response)
        end
      rescue *RESCUED_EXCEPTIONS => e
        raise HTTPConnectionError.new(address, e)
      end
    end
Make an HTTP request with the given verb, data, params, and headers. If
 the response has a return type of JSON, the JSON is automatically parsed
 and returned as a hash; otherwise it is returned as a string.

 @raise [HTTPError]
   if the request is not an HTTP 200 OK

 @param [Symbol] verb
   the lowercase symbol of the HTTP verb (e.g. :get, :delete)
 @param [String] path
   the absolute or relative path from {Defaults.address} to make the
   request against
 @param [#read, Hash, nil] data
   the data to use (varies based on the +verb+)
 @param [Hash] headers
   the list of headers to use

 @return [String, Hash]
   the response body