Skip to content

Commit fc50894

Browse files
committed
fix: check content-type when using referrers API
Return an ErrUnsupported to when the referrers API is not supported. Signed-off-by: Kyle M. Tarplee <kmtarplee@ieee.org>
1 parent 9febd7b commit fc50894

File tree

5 files changed

+265
-124
lines changed

5 files changed

+265
-124
lines changed

example_copy_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ func TestMain(m *testing.M) {
144144
MediaType: ocispec.MediaTypeImageIndex,
145145
Manifests: referrers,
146146
}
147+
w.Header().Set("Content-Type", ocispec.MediaTypeImageIndex)
147148
if err := json.NewEncoder(w).Encode(result); err != nil {
148149
panic(err)
149150
}

extendedcopy_test.go

+18-4
Original file line numberDiff line numberDiff line change
@@ -1031,15 +1031,20 @@ func TestExtendedCopyGraph_FilterAnnotationWithMultipleRegex_Referrers(t *testin
10311031
// set up test server
10321032
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
10331033
p := r.URL.Path
1034+
var manifests []ocispec.Descriptor
10341035
switch {
10351036
case p == "/v2/test/referrers/"+descs[0].Digest.String():
1037+
manifests = descs[1:]
1038+
fallthrough
1039+
case strings.HasPrefix(p, "/v2/test/referrers/"):
10361040
result := ocispec.Index{
10371041
Versioned: specs.Versioned{
10381042
SchemaVersion: 2, // historical value. does not pertain to OCI or docker version
10391043
},
10401044
MediaType: ocispec.MediaTypeImageIndex,
1041-
Manifests: descs[1:],
1045+
Manifests: manifests,
10421046
}
1047+
w.Header().Set("Content-Type", ocispec.MediaTypeImageIndex)
10431048
if err := json.NewEncoder(w).Encode(result); err != nil {
10441049
t.Errorf("failed to write response: %v", err)
10451050
}
@@ -1076,7 +1081,6 @@ func TestExtendedCopyGraph_FilterAnnotationWithMultipleRegex_Referrers(t *testin
10761081
default:
10771082
t.Errorf("unexpected access: %s %s", r.Method, r.URL)
10781083
w.WriteHeader(http.StatusNotFound)
1079-
return
10801084
}
10811085
}))
10821086
defer ts.Close()
@@ -1454,15 +1458,20 @@ func TestExtendedCopyGraph_FilterArtifactTypeWithMultipleRegex_Referrers(t *test
14541458
// set up test server
14551459
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
14561460
p := r.URL.Path
1461+
var manifests []ocispec.Descriptor
14571462
switch {
14581463
case p == "/v2/test/referrers/"+descs[0].Digest.String():
1464+
manifests = descs[1:]
1465+
fallthrough
1466+
case strings.HasPrefix(p, "/v2/test/referrers/"):
14591467
result := ocispec.Index{
14601468
Versioned: specs.Versioned{
14611469
SchemaVersion: 2, // historical value. does not pertain to OCI or docker version
14621470
},
14631471
MediaType: ocispec.MediaTypeImageIndex,
1464-
Manifests: descs[1:],
1472+
Manifests: manifests,
14651473
}
1474+
w.Header().Set("Content-Type", ocispec.MediaTypeImageIndex)
14661475
if err := json.NewEncoder(w).Encode(result); err != nil {
14671476
t.Errorf("failed to write response: %v", err)
14681477
}
@@ -1695,15 +1704,20 @@ func TestExtendedCopyGraph_FilterArtifactTypeAndAnnotationWithMultipleRegex_Refe
16951704
// set up test server
16961705
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
16971706
p := r.URL.Path
1707+
var manifests []ocispec.Descriptor
16981708
switch {
16991709
case p == "/v2/test/referrers/"+descs[0].Digest.String():
1710+
manifests = descs[1:]
1711+
fallthrough
1712+
case strings.HasPrefix(p, "/v2/test/referrers/"):
17001713
result := ocispec.Index{
17011714
Versioned: specs.Versioned{
17021715
SchemaVersion: 2, // historical value. does not pertain to OCI or docker version
17031716
},
17041717
MediaType: ocispec.MediaTypeImageIndex,
1705-
Manifests: descs[1:],
1718+
Manifests: manifests,
17061719
}
1720+
w.Header().Set("Content-Type", ocispec.MediaTypeImageIndex)
17071721
if err := json.NewEncoder(w).Encode(result); err != nil {
17081722
t.Errorf("failed to write response: %v", err)
17091723
}

registry/remote/example_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,17 @@ func TestMain(m *testing.M) {
174174
w.Header().Set("Content-Digest", string(blobDescriptor.Digest))
175175
w.Header().Set("Content-Length", strconv.Itoa(len(blobContent)))
176176
w.Write([]byte(blobContent))
177+
case p == fmt.Sprintf("/v2/%s/referrers/%s", exampleRepositoryName, "sha256:0000000000000000000000000000000000000000000000000000000000000000"):
178+
result := ocispec.Index{
179+
Versioned: specs.Versioned{
180+
SchemaVersion: 2, // historical value. does not pertain to OCI or docker version
181+
},
182+
MediaType: ocispec.MediaTypeImageIndex,
183+
}
184+
w.Header().Set("Content-Type", ocispec.MediaTypeImageIndex)
185+
if err := json.NewEncoder(w).Encode(result); err != nil {
186+
panic(err)
187+
}
177188
case p == fmt.Sprintf("/v2/%s/referrers/%s", exampleRepositoryName, exampleManifestDescriptor.Digest.String()):
178189
q := r.URL.Query()
179190
var referrers []ocispec.Descriptor
@@ -191,6 +202,7 @@ func TestMain(m *testing.M) {
191202
MediaType: ocispec.MediaTypeImageIndex,
192203
Manifests: referrers,
193204
}
205+
w.Header().Set("Content-Type", ocispec.MediaTypeImageIndex)
194206
if err := json.NewEncoder(w).Encode(result); err != nil {
195207
panic(err)
196208
}

registry/remote/repository.go

+18-8
Original file line numberDiff line numberDiff line change
@@ -483,16 +483,14 @@ func (r *Repository) Referrers(ctx context.Context, desc ocispec.Descriptor, art
483483

484484
// The referrers state is unknown.
485485
if err != nil {
486-
var errResp *errcode.ErrorResponse
487-
if !errors.As(err, &errResp) || errResp.StatusCode != http.StatusNotFound {
486+
if !errors.Is(err, errdef.ErrUnsupported) {
488487
return err
489488
}
490-
if errutil.IsErrorCode(errResp, errcode.ErrorCodeNameUnknown) {
489+
if errutil.IsErrorCode(err, errcode.ErrorCodeNameUnknown) {
491490
// The repository is not found, no fallback.
492491
return err
493492
}
494-
// A 404 returned by Referrers API indicates that Referrers API is
495-
// not supported. Fallback to referrers tag schema.
493+
// Fallback to referrers tag schema.
496494
r.SetReferrersCapability(false)
497495
return r.referrersByTagSchema(ctx, desc, artifactType, fn)
498496
}
@@ -544,10 +542,21 @@ func (r *Repository) referrersPageByAPI(ctx context.Context, artifactType string
544542
}
545543
defer resp.Body.Close()
546544

547-
if resp.StatusCode != http.StatusOK {
545+
switch resp.StatusCode {
546+
case http.StatusOK:
547+
case http.StatusNotFound:
548+
// A 404 returned by Referrers API indicates that Referrers API is not supported.
549+
return "", errors.Join(errdef.ErrUnsupported, errutil.ParseErrorResponse(resp))
550+
default:
548551
return "", errutil.ParseErrorResponse(resp)
549552
}
550553

554+
// also check the content type
555+
if ct := resp.Header.Get("Content-Type"); ct != ocispec.MediaTypeImageIndex {
556+
err := errors.Join(errdef.ErrUnsupported, errutil.ParseErrorResponse(resp))
557+
return "", fmt.Errorf("unknown content returned (%s), expecting image index: %w", ct, err)
558+
}
559+
551560
var index ocispec.Index
552561
lr := limitReader(resp.Body, r.MaxMetadataBytes)
553562
if err := json.NewDecoder(lr).Decode(&index); err != nil {
@@ -657,8 +666,9 @@ func (r *Repository) pingReferrers(ctx context.Context) (bool, error) {
657666

658667
switch resp.StatusCode {
659668
case http.StatusOK:
660-
r.SetReferrersCapability(true)
661-
return true, nil
669+
supported := resp.Header.Get("Content-Type") == ocispec.MediaTypeImageIndex
670+
r.SetReferrersCapability(supported)
671+
return supported, nil
662672
case http.StatusNotFound:
663673
if err := errutil.ParseErrorResponse(resp); errutil.IsErrorCode(err, errcode.ErrorCodeNameUnknown) {
664674
// repository not found

0 commit comments

Comments
 (0)