func (r *Session) GetRemoteImageLayer(imgID, registry string, token []string, imgSize int64) (io.ReadCloser, error) { var ( retries = 5 statusCode = 0 client *http.Client res *http.Response imageURL = fmt.Sprintf("%simages/%s/layer", registry, imgID) ) req, err := r.reqFactory.NewRequest("GET", imageURL, nil) if err != nil { return nil, fmt.Errorf("Error while getting from the server: %s\n", err) } setTokenAuth(req, token) for i := 1; i <= retries; i++ { statusCode = 0 res, client, err = r.doRequest(req) if err != nil { log.Debugf("Error contacting registry: %s", err) if res != nil { if res.Body != nil { res.Body.Close() } statusCode = res.StatusCode } if i == retries { return nil, fmt.Errorf("Server error: Status %d while fetching image layer (%s)", statusCode, imgID) } time.Sleep(time.Duration(i) * 5 * time.Second) continue } break } if res.StatusCode != 200 { res.Body.Close() return nil, fmt.Errorf("Server error: Status %d while fetching image layer (%s)", res.StatusCode, imgID) } if res.Header.Get("Accept-Ranges") == "bytes" && imgSize > 0 { log.Debugf("server supports resume") return httputils.ResumableRequestReaderWithInitialResponse(client, req, 5, imgSize, res), nil } log.Debugf("server doesn't support resume") return res.Body, nil }
func (r *Session) GetRemoteImageLayer(imgID, registry string, imgSize int64) (io.ReadCloser, error) { var ( retries = 5 statusCode = 0 res *http.Response err error imageURL = fmt.Sprintf("%simages/%s/layer", registry, imgID) ) req, err := http.NewRequest("GET", imageURL, nil) if err != nil { return nil, fmt.Errorf("Error while getting from the server: %v", err) } // TODO: why are we doing retries at this level? // These retries should be generic to both v1 and v2 for i := 1; i <= retries; i++ { statusCode = 0 res, err = r.client.Do(req) if err == nil { break } logrus.Debugf("Error contacting registry %s: %v", registry, err) if res != nil { if res.Body != nil { res.Body.Close() } statusCode = res.StatusCode } if i == retries { return nil, fmt.Errorf("Server error: Status %d while fetching image layer (%s)", statusCode, imgID) } time.Sleep(time.Duration(i) * 5 * time.Second) } if res.StatusCode != 200 { res.Body.Close() return nil, fmt.Errorf("Server error: Status %d while fetching image layer (%s)", res.StatusCode, imgID) } if res.Header.Get("Accept-Ranges") == "bytes" && imgSize > 0 { logrus.Debugf("server supports resume") return httputils.ResumableRequestReaderWithInitialResponse(r.client, req, 5, imgSize, res), nil } logrus.Debugf("server doesn't support resume") return res.Body, nil }
// GetRemoteImageLayer retrieves an image layer from the registry func (r *Session) GetRemoteImageLayer(imgID, registry string, imgSize int64) (io.ReadCloser, error) { var ( statusCode = 0 res *http.Response err error imageURL = fmt.Sprintf("%simages/%s/layer", registry, imgID) ) req, err := http.NewRequest("GET", imageURL, nil) if err != nil { return nil, fmt.Errorf("Error while getting from the server: %v", err) } statusCode = 0 res, err = r.client.Do(req) if err != nil { logrus.Debugf("Error contacting registry %s: %v", registry, err) // the only case err != nil && res != nil is https://golang.org/src/net/http/client.go#L515 if res != nil { if res.Body != nil { res.Body.Close() } statusCode = res.StatusCode } return nil, fmt.Errorf("Server error: Status %d while fetching image layer (%s)", statusCode, imgID) } if res.StatusCode != 200 { res.Body.Close() return nil, fmt.Errorf("Server error: Status %d while fetching image layer (%s)", res.StatusCode, imgID) } if res.Header.Get("Accept-Ranges") == "bytes" && imgSize > 0 { logrus.Debugf("server supports resume") return httputils.ResumableRequestReaderWithInitialResponse(r.client, req, 5, imgSize, res), nil } logrus.Debugf("server doesn't support resume") return res.Body, nil }