diff --git a/registry/docker/manifest.go b/registry/docker/manifest.go index 0944ab3ca..ea9c51ea3 100644 --- a/registry/docker/manifest.go +++ b/registry/docker/manifest.go @@ -15,22 +15,24 @@ func (r *Registry) ManifestDigest(repository, reference string) (digest.Digest, url := r.url("/v2/%s/manifests/%s", repository, reference) r.Logf("registry.manifest.head url=%s repository=%s reference=%s", url, repository, reference) - req, err := http.NewRequest("GET", url, nil) + // Try HEAD request first because it's free + resp, err := r.request("HEAD", url) if err != nil { return "", err } - req.Header.Set("Accept", strings.Join([]string{manifestv2.MediaTypeManifest, oci.MediaTypeImageIndex, oci.MediaTypeImageManifest}, ",")) - resp, err := r.Client.Do(req) + if hdr := resp.Header.Get("Docker-Content-Digest"); hdr != "" { + return digest.Parse(hdr) + } + + // HEAD request didn't return a digest, attempt to fetch digest from body + r.Logf("registry.manifest.get url=%s repository=%s reference=%s", url, repository, reference) + resp, err = r.request("GET", url) if err != nil { return "", err } defer resp.Body.Close() - if hdr := resp.Header.Get("Docker-Content-Digest"); hdr != "" { - return digest.Parse(hdr) - } - // Try to get digest from body instead, should be equal to what would be presented // in Docker-Content-Digest body, err := ioutil.ReadAll(resp.Body) @@ -39,3 +41,19 @@ func (r *Registry) ManifestDigest(repository, reference string) (digest.Digest, } return digest.FromBytes(body), nil } + +// request performs a request against a url +func (r *Registry) request(method string, url string) (*http.Response, error) { + req, err := http.NewRequest(method, url, nil) + if err != nil { + return nil, err + } + + req.Header.Set("Accept", strings.Join([]string{manifestv2.MediaTypeManifest, oci.MediaTypeImageIndex, oci.MediaTypeImageManifest}, ",")) + resp, err := r.Client.Do(req) + if err != nil { + return nil, err + } + + return resp, nil +} diff --git a/registry/docker/manifest_test.go b/registry/docker/manifest_test.go index d8101e871..c8d238006 100644 --- a/registry/docker/manifest_test.go +++ b/registry/docker/manifest_test.go @@ -1,7 +1,9 @@ package docker import ( + "bytes" "io" + "io/ioutil" "net/http" "net/http/httptest" "testing" @@ -24,9 +26,13 @@ func TestGetDigest(t *testing.T) { } defer resp.Body.Close() + bodyBytes, _ := ioutil.ReadAll(resp.Body) ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Add("content-type", "application/vnd.docker.distribution.manifest.v2+json; charset=ISO-8859-1") io.Copy(w, resp.Body) + + // Reset body for additional calls + resp.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes)) })) defer ts.Close()