request.go
func (client *Client) doJsonRequestUnredacted(method, api string,
	reqbody, out interface{}) error {
	req, err := client.createRequest(method, api, reqbody)
	if err != nil {
		return err
	}

	// Perform the request and retry it if it's not a POST or PUT request
	var resp *http.Response
	if method == "POST" || method == "PUT" {
		resp, err = client.HttpClient.Do(req)
	} else {
		resp, err = client.doRequestWithRetries(req, client.RetryTimeout)
	}
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode < 200 || resp.StatusCode > 299 {
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return err
		}
		return fmt.Errorf("API error %s: %s", resp.Status, body)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	// If we got no body, by default let's just make an empty JSON dict. This
	// saves us some work in other parts of the code.
	if len(body) == 0 {
		body = []byte{'{', '}'}
	}

	// Try to parse common response fields to check whether there's an error reported in a response.
	var common *Response
	err = json.Unmarshal(body, &common)
	if err != nil {
		// UnmarshalTypeError errors are ignored, because in some cases API response is an array that cannot be
		// unmarshalled into a struct.
		_, ok := err.(*json.UnmarshalTypeError)
		if !ok {
			return err
		}
	}
	if common != nil && common.Status == "error" {
		return fmt.Errorf("API returned error: %s", common.Error)
	}

	// If they don't care about the body, then we don't care to give them one,
	// so bail out because we're done.
	if out == nil {
		return nil
	}

	return json.Unmarshal(body, &out)
}
func (client *Client) doJsonRequestUnredacted(method, api string,
	reqbody, out interface{}) error {
	req, err := client.createRequest(method, api, reqbody)
	if err != nil {
		return err
	}

	// Perform the request and retry it if it's not a POST or PUT request
	var resp *http.Response
	if method == "POST" || method == "PUT" {
		resp, err = client.HttpClient.Do(req)
	} else {
		resp, err = client.doRequestWithRetries(req, client.RetryTimeout)
	}
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode < 200 || resp.StatusCode > 299 {
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return err
		}
		return fmt.Errorf("API error %s: %s", resp.Status, body)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	// If we got no body, by default let's just make an empty JSON dict. This
	// saves us some work in other parts of the code.
	if len(body) == 0 {
		body = []byte{'{', '}'}
	}

	// Try to parse common response fields to check whether there's an error reported in a response.
	var common *Response
	err = json.Unmarshal(body, &common)
	if err != nil {
		// UnmarshalTypeError errors are ignored, because in some cases API response is an array that cannot be
		// unmarshalled into a struct.
		_, ok := err.(*json.UnmarshalTypeError)
		if !ok {
			return err
		}
	}
	if common != nil && common.Status == "error" {
		return fmt.Errorf("API returned error: %s", common.Error)
	}

	// If they don't care about the body, then we don't care to give them one,
	// so bail out because we're done.
	if out == nil {
		return nil
	}

	return json.Unmarshal(body, &out)
}
// doJsonRequestUnredacted is the simplest type of request: a method on a URI that returns
// some JSON result which we unmarshal into the passed interface.