func fetch()

in getdeps/fetch.go [22:84]


func fetch(label, urlStr string) ([]byte, error) {
	log.Printf("%s: Downloading %s...", label, urlStr)

	// Get the data
	var (
		resp *http.Response
		err  error
	)
	client := &http.Client{
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			// some servers will behave differently upon redirects if a Referer
			// header is found, and this may cause the download to fail. So here
			// we remove the Referer header.
			req.Header.Del("Referer")
			return nil
		},
	}
	req, err := http.NewRequest("GET", urlStr, nil)
	if err != nil {
		return nil, fmt.Errorf("Failed to create new http.Request: %w", err)
	}
	for attempts := 0; attempts < 3; attempts++ {
		resp, err = client.Do(req)
		if err != nil {
			if uErr, ok := err.(*url.Error); ok {
				if uErr.Temporary() || uErr.Timeout() {
					// retryable error
					log.Printf("Failed to get file, trying again. Error was: %v", err)
					continue
				}
			}
			// non-retryable error
			return nil, fmt.Errorf("%s: error while downloading %s: %w", label, urlStr, err)
		}
		defer resp.Body.Close()
		log.Printf("Status code is %s", resp.Status)
		break
	}
	// At this point either the last attempt succeeded, or it failed with
	// a retryable error, but we are out of retrie.
	if err != nil {
		return nil, fmt.Errorf("every download attempt has failed. Last error: %v", err)
	}

	var data []byte
	for attempts := 0; attempts < 3; attempts++ {
		data, err = ioutil.ReadAll(resp.Body)
		if err != nil {
			switch err {
			case io.ErrUnexpectedEOF, io.ErrClosedPipe:
				// retryable error
				log.Printf("Failed to retrieve file, trying again. Error was: %v", err)
				continue
			default:
				// non-retryable error
				return nil, fmt.Errorf("%s: error while downloading %s: %w", label, urlStr, err)
			}
		} else {
			break
		}
	}
	return data, nil
}