Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions pkg/image/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,23 @@ package image
import "fmt"

var (
// ManifestListMimeType is the mime type used to get the manifest list
// ManifestListMimeType is the mime type used to get the manifest list (Docker)
ManifestListMimeType = "application/vnd.docker.distribution.manifest.list.v2+json"

// ManifestMimeType is the mime type used to get the manifest
// ManifestMimeType is the mime type used to get the manifest (Docker)
ManifestMimeType = "application/vnd.docker.distribution.manifest.v2+json"

// OCIIndexMimeType is the mime type for OCI image indexes (multi-arch)
OCIIndexMimeType = "application/vnd.oci.image.index.v1+json"

// OCIManifestMimeType is the mime type for OCI image manifests
OCIManifestMimeType = "application/vnd.oci.image.manifest.v1+json"

// AcceptManifestList is the Accept header value for manifest list requests
AcceptManifestList = ManifestListMimeType + ", " + OCIIndexMimeType

// AcceptManifest is the Accept header value for manifest requests
AcceptManifest = ManifestMimeType + ", " + OCIManifestMimeType
)

// ManifestList represents the Docker Manifest List:
Expand Down
13 changes: 7 additions & 6 deletions pkg/image/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (r *Remote) WithPlatform(p *Platform) {
func (r *Remote) ManifestList() (*ManifestList, error) {

// not having a manifest list is no error
res, err := r.request("GET", ManifestListMimeType, "manifests", r.url.Reference())
res, err := r.request("GET", AcceptManifestList, "manifests", r.url.Reference())
if err != nil {
return nil, nil
}
Expand All @@ -111,14 +111,15 @@ func (r *Remote) Manifest() (*Manifest, error) {
}

// it should almost certainly be fetchable at this point
res, err := r.request("GET", ManifestMimeType, "manifests", digest)
res, err := r.request("GET", AcceptManifest, "manifests", digest)
if err != nil {
return nil, fmt.Errorf("error requesting manifest@%s: %v", digest, err)
}

// if the server responds with a manifest list, our digest is not correct
if res.Header.Get("Content-Type") != ManifestMimeType {
return nil, fmt.Errorf("content type for %s cannot be %s", digest, res.Header.Get("Content-Type"))
// if the server responds with a manifest list/index, our digest is not correct
ct := res.Header.Get("Content-Type")
if ct != ManifestMimeType && ct != OCIManifestMimeType {
return nil, fmt.Errorf("content type for %s cannot be %s", digest, ct)
}

// we must also be able to parse it
Expand Down Expand Up @@ -152,7 +153,7 @@ func (r *Remote) Digest() (string, error) {
// if there's no list and no platform, fall back to whatever the server
// gives us through the docker-content-digest header
if r.platform == nil && (lst == nil || len(lst.Manifests) == 0) {
res, err := r.request("HEAD", ManifestMimeType, "manifests", r.url.Reference())
res, err := r.request("HEAD", AcceptManifest, "manifests", r.url.Reference())

if err != nil {
return "", fmt.Errorf("failed to fetch manifest: %v", err)
Expand Down
14 changes: 11 additions & 3 deletions pkg/image/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func requireSupportedMimeTypes(client *http.Client, url URL) error {
ref := url.Endpoint("manifests", url.Reference())

req := mustNewRequest("HEAD", ref)
req.Header.Add("Accept", fmt.Sprintf("%s, */*", ManifestMimeType))
req.Header.Add("Accept", AcceptManifest+", "+AcceptManifestList+", */*")

res, err := client.Do(req)
if err != nil {
Expand All @@ -37,9 +37,17 @@ func requireSupportedMimeTypes(client *http.Client, url URL) error {
}

mime := res.Header.Get("Content-Type")
if mime != ManifestMimeType && mime != ManifestListMimeType {
return fmt.Errorf("no schema version 2 support by %s", url)
if !isSupportedMimeType(mime) {
return fmt.Errorf("unsupported manifest type %s from %s", mime, url)
}

return nil
}

func isSupportedMimeType(mime string) bool {
switch mime {
case ManifestMimeType, ManifestListMimeType, OCIManifestMimeType, OCIIndexMimeType:
return true
}
return false
}