diff --git a/ociregistry/ociclient/client.go b/ociregistry/ociclient/client.go index 842f524..bc78b32 100644 --- a/ociregistry/ociclient/client.go +++ b/ociregistry/ociclient/client.go @@ -124,18 +124,25 @@ type client struct { listPageSize int } +type descriptorRequired byte + +const ( + requireSize descriptorRequired = 1 << iota + requireDigest +) + // descriptorFromResponse tries to form a descriptor from an HTTP response, // filling in the Digest field using knownDigest if it's not present. // // Note: this implies that the Digest field will be empty if there is no // digest in the response and knownDigest is empty. -func descriptorFromResponse(resp *http.Response, knownDigest digest.Digest, requireSize bool) (ociregistry.Descriptor, error) { +func descriptorFromResponse(resp *http.Response, knownDigest digest.Digest, require descriptorRequired) (ociregistry.Descriptor, error) { contentType := resp.Header.Get("Content-Type") if contentType == "" { contentType = "application/octet-stream" } size := int64(0) - if requireSize { + if (require & requireSize) != 0 { if resp.StatusCode == http.StatusPartialContent { contentRange := resp.Header.Get("Content-Range") if contentRange == "" { @@ -165,6 +172,9 @@ func descriptorFromResponse(resp *http.Response, knownDigest digest.Digest, requ } else { digest = knownDigest } + if (require&requireDigest) != 0 && digest == "" { + return ociregistry.Descriptor{}, fmt.Errorf("no digest found in response") + } return ociregistry.Descriptor{ Digest: digest, MediaType: contentType, diff --git a/ociregistry/ociclient/reader.go b/ociregistry/ociclient/reader.go index ba942f4..6888584 100644 --- a/ociregistry/ociclient/reader.go +++ b/ociregistry/ociclient/reader.go @@ -60,7 +60,7 @@ func (c *client) GetBlobRange(ctx context.Context, repo string, digest ociregist // Fix that either by returning ErrUnsupported or by reading the whole // blob and returning only the required portion. defer closeOnError(&_err, resp.Body) - desc, err := descriptorFromResponse(resp, ociregistry.Digest(rreq.Digest), true) + desc, err := descriptorFromResponse(resp, ociregistry.Digest(rreq.Digest), requireSize) if err != nil { return nil, fmt.Errorf("invalid descriptor in response: %v", err) } @@ -97,7 +97,7 @@ func (c *client) resolve(ctx context.Context, rreq *ocirequest.Request) (ociregi return ociregistry.Descriptor{}, err } resp.Body.Close() - desc, err := descriptorFromResponse(resp, ociregistry.Digest(rreq.Digest), true) + desc, err := descriptorFromResponse(resp, ociregistry.Digest(rreq.Digest), requireSize|requireDigest) if err != nil { return ociregistry.Descriptor{}, fmt.Errorf("invalid descriptor in response: %v", err) } @@ -138,7 +138,7 @@ func (c *client) read(ctx context.Context, rreq *ocirequest.Request) (_ ociregis return nil, err } defer closeOnError(&_err, resp.Body) - desc, err := descriptorFromResponse(resp, ociregistry.Digest(rreq.Digest), true) + desc, err := descriptorFromResponse(resp, ociregistry.Digest(rreq.Digest), requireSize) if err != nil { return nil, fmt.Errorf("invalid descriptor in response: %v", err) } @@ -176,13 +176,10 @@ func (c *client) read(ctx context.Context, rreq *ocirequest.Request) (_ ociregis return nil, err } resp1.Body.Close() - desc, err = descriptorFromResponse(resp1, ociregistry.Digest(rreq1.Digest), true) + desc, err = descriptorFromResponse(resp1, ociregistry.Digest(rreq1.Digest), requireSize|requireDigest) if err != nil { return nil, err } - if desc.Digest == "" { - return nil, fmt.Errorf("no digest header found in response") - } } } return newBlobReader(resp.Body, desc), nil diff --git a/ociregistry/ociclient/writer.go b/ociregistry/ociclient/writer.go index 3d8fc3c..47ac6bc 100644 --- a/ociregistry/ociclient/writer.go +++ b/ociregistry/ociclient/writer.go @@ -82,7 +82,8 @@ func (c *client) MountBlob(ctx context.Context, fromRepo, toRepo string, dig oci // return Unsupported. return ociregistry.Descriptor{}, fmt.Errorf("registry does not support mounts: %w", ociregistry.ErrUnsupported) } - return descriptorFromResponse(resp, dig, false) + // TODO: is it OK to omit the size from the returned descriptor here? + return descriptorFromResponse(resp, dig, requireDigest) } func (c *client) PushBlob(ctx context.Context, repo string, desc ociregistry.Descriptor, r io.Reader) (_ ociregistry.Descriptor, _err error) {