diff --git a/registry/digest.go b/registry/digest.go index 361ae4748..b9f5da4a1 100644 --- a/registry/digest.go +++ b/registry/digest.go @@ -2,6 +2,7 @@ package registry import ( "context" + _ "crypto/sha256" "fmt" "net/http" @@ -9,6 +10,8 @@ import ( digest "github.com/opencontainers/go-digest" ) +var useHead bool = true + // Digest returns the digest for an image. func (r *Registry) Digest(ctx context.Context, image Image) (digest.Digest, error) { if len(image.Digest) > 1 { @@ -36,5 +39,38 @@ func (r *Registry) Digest(ctx context.Context, image Image) (digest.Digest, erro return "", fmt.Errorf("got status code: %d", resp.StatusCode) } - return digest.Parse(resp.Header.Get("Docker-Content-Digest")) + d := resp.Header.Get("Docker-Content-Digest") + if d == "" { + req, err := http.NewRequest("HEAD", url, nil) + if err != nil { + return "", err + } + + req.Header.Add("Accept", schema2.MediaTypeManifest) + resp, err := r.Client.Do(req.WithContext(ctx)) + if err != nil { + return "", err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNotFound { + return "", fmt.Errorf("got status code: %d", resp.StatusCode) + } + + d = resp.Header.Get("Docker-Content-Digest") + if d == "" { + useHead = false + } + } + if d == "" { + // Get the v2 manifest. + m, err := r.Manifest(ctx, image.Path, image.Reference()) + if err != nil { + return "", err + } + _, p, _ := m.Payload() + return digest.FromBytes(p), nil + } + + return digest.Parse(d) }