func()

in metadata/metadata.go [485:550]


func (c *Client) do(ctx context.Context, cfg requestConfig) (*http.Response, error) {
	finalURL, err := url.Parse(cfg.baseURL)
	if err != nil {
		return nil, fmt.Errorf("failed to parse url: %+v", err)
	}

	values := finalURL.Query()

	if cfg.hang {
		values.Add("wait_for_change", "true")
		values.Add("last_etag", c.etag)
	}

	if cfg.timeout > 0 {
		values.Add("timeout_sec", fmt.Sprintf("%d", cfg.timeout))
	}

	if cfg.recursive {
		values.Add("recursive", "true")
	}

	if cfg.jsonOutput {
		values.Add("alt", "json")
	}

	finalURL.RawQuery = values.Encode()
	logger.Debugf("Requesting(GET) MDS URL: %s", finalURL.String())

	req, err := http.NewRequestWithContext(ctx, "GET", finalURL.String(), nil)
	if err != nil {
		return nil, err
	}

	req.Header.Add("Metadata-Flavor", "Google")
	for k, v := range cfg.headers {
		req.Header.Add(k, v)
	}
	resp, err := c.httpClient.Do(req)

	// If we are canceling httpClient will also wrap the context's error so
	// check first the context.
	if ctx.Err() != nil {
		return resp, ctx.Err()
	}

	if err != nil {
		return resp, fmt.Errorf("error connecting to metadata server: %+v", err)
	}

	if resp == nil {
		return nil, fmt.Errorf("got nil response from metadata server")
	}

	if resp.StatusCode != http.StatusOK {
		defer resp.Body.Close()
		// Ignore read error as we are returning original error and wrapping MDS error code.
		r, _ := io.ReadAll(resp.Body)
		return resp, fmt.Errorf("invalid response from metadata server, status code: %d, reason: %s", resp.StatusCode, string(r))
	}

	if cfg.hang {
		c.updateEtag(resp)
	}

	return resp, nil
}