client.go
func (c *Client) httpRequest(method string, path string, data []byte, headers map[string]string, useCoordinator bool) (*http.Response, []byte, error) {
	if data == nil {
		data = []byte{}
	}

	// try at most maxHosts non-failed hosts; protect against broken cluster.removeHost
	var response *http.Response
	var err error
	for i := 0; i < maxHosts; i++ {
		host, err := c.host(useCoordinator)
		if err != nil {
			return nil, nil, err
		}
		response, err = c.doRequest(host, method, path, c.augmentHeaders(headers), bytes.NewReader(data))
		if err == nil {
			break
		}
		if c.manualServerURI == nil {
			if useCoordinator {
				c.coordinatorLock.Lock()
				c.coordinatorURI = nil
				c.coordinatorLock.Unlock()
			} else {
				c.cluster.RemoveHost(host)
			}
		}
		// TODO: exponential backoff
		time.Sleep(1 * time.Second)
	}
	if response == nil {
		return nil, nil, ErrTriedMaxHosts
	}
	defer response.Body.Close()
	warning := response.Header.Get("warning")
	if warning != "" {
		c.logger.Println(warning)
	}
	// TODO: Optimize buffer creation
	buf, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, nil, err
	}
	if response.StatusCode < 200 || response.StatusCode >= 300 {
		err := NewError(fmt.Sprintf("Server error (%d) %s: %s", response.StatusCode, response.Status, string(buf)))
		return response, buf, err
	}
	return response, buf, nil
}
func (c *Client) httpRequest(method string, path string, data []byte, headers map[string]string, useCoordinator bool) (*http.Response, []byte, error) {
	if data == nil {
		data = []byte{}
	}

	// try at most maxHosts non-failed hosts; protect against broken cluster.removeHost
	var response *http.Response
	var err error
	for i := 0; i < maxHosts; i++ {
		host, err := c.host(useCoordinator)
		if err != nil {
			return nil, nil, err
		}
		response, err = c.doRequest(host, method, path, c.augmentHeaders(headers), bytes.NewReader(data))
		if err == nil {
			break
		}
		if c.manualServerURI == nil {
			if useCoordinator {
				c.coordinatorLock.Lock()
				c.coordinatorURI = nil
				c.coordinatorLock.Unlock()
			} else {
				c.cluster.RemoveHost(host)
			}
		}
		// TODO: exponential backoff
		time.Sleep(1 * time.Second)
	}
	if response == nil {
		return nil, nil, ErrTriedMaxHosts
	}
	defer response.Body.Close()
	warning := response.Header.Get("warning")
	if warning != "" {
		c.logger.Println(warning)
	}
	// TODO: Optimize buffer creation
	buf, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, nil, err
	}
	if response.StatusCode < 200 || response.StatusCode >= 300 {
		err := NewError(fmt.Sprintf("Server error (%d) %s: %s", response.StatusCode, response.Status, string(buf)))
		return response, buf, err
	}
	return response, buf, nil
}
// httpRequest makes a request to the cluster - use this when you want the
// client to choose a host, and it doesn't matter if the request goes to a
// specific host