Search through all the base URLs to connect to one that works.

    This is a thin wrapper around requests.request() so most parameters are
    documented there.

    Args:
      path: The URL path to access in this endpoint.
      verify_cb: A callback which should return True if the response is
        reasonable. This is used to detect if we are able to talk to the correct
        endpoint. If not we try a different endpoint/proxy combination.
      data: Parameters to send in POST bodies (See Requests documentation).
      params: Parameters to send in GET URLs (See Requests documentation).
      headers: Additional headers (See Requests documentation)
      method: The HTTP method to use. If not set we select one automatically.
      timeout: See Requests documentation.

    Returns:
      an HTTPObject() instance with the correct error code set.

def OpenServerEndpoint(self,
                         path,
                         verify_cb=lambda x: True,
                         data=None,
                         params=None,
                         headers=None,
                         method="GET",
                         timeout=None):
    """Search through all the base URLs to connect to one that works.

    This is a thin wrapper around requests.request() so most parameters are
    documented there.

    Args:
      path: The URL path to access in this endpoint.
      verify_cb: A callback which should return True if the response is
        reasonable. This is used to detect if we are able to talk to the correct
        endpoint. If not we try a different endpoint/proxy combination.
      data: Parameters to send in POST bodies (See Requests documentation).
      params: Parameters to send in GET URLs (See Requests documentation).
      headers: Additional headers (See Requests documentation)
      method: The HTTP method to use. If not set we select one automatically.
      timeout: See Requests documentation.

    Returns:
      an HTTPObject() instance with the correct error code set.
    """
    tries = 0
    last_error = HTTPObject(code=404)

    while tries < len(self.base_urls):
      base_url_index = self.last_base_url_index % len(self.base_urls)
      active_base_url = self.base_urls[base_url_index]

      result = self.OpenURL(
          self._ConcatenateURL(active_base_url, path),
          data=data,
          params=params,
          headers=headers,
          method=method,
          timeout=timeout,
          verify_cb=verify_cb,
      )

      if not result.Success():
        tries += 1
        self.last_base_url_index += 1
        last_error = result
        continue

      # The URL worked - we record that.
      self.active_base_url = active_base_url

      return result

    # No connection is possible at all.
    logging.info(
        "Could not connect to GRR servers %s, directly or through "
        "these proxies: %s.", self.base_urls, self.proxies)

    return last_error