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
}