forked from TrueCloudLab/distribution
Support HEAD requests without Docker-Content-Digest header
A statically hosted registry that responds correctly to GET with a manifest will load the right digest (by looking at the manifest body and calculating the digest). If the registry returns a HEAD without `Docker-Content-Digest`, then the client Tags().Get() call will return an empty digest. This commit changes the client to fallback to loading the tag via GET if the `Docker-Content-Digest` header is not set. Signed-off-by: Clayton Coleman <ccoleman@redhat.com>
This commit is contained in:
parent
d9e0121fef
commit
a2015272c1
2 changed files with 63 additions and 1 deletions
|
@ -321,7 +321,8 @@ func (t *tags) Get(ctx context.Context, tag string) (distribution.Descriptor, er
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case resp.StatusCode >= 200 && resp.StatusCode < 400:
|
case resp.StatusCode >= 200 && resp.StatusCode < 400 && len(resp.Header.Get("Docker-Content-Digest")) > 0:
|
||||||
|
// if the response is a success AND a Docker-Content-Digest can be retrieved from the headers
|
||||||
return descriptorFromResponse(resp)
|
return descriptorFromResponse(resp)
|
||||||
default:
|
default:
|
||||||
// if the response is an error - there will be no body to decode.
|
// if the response is an error - there will be no body to decode.
|
||||||
|
|
|
@ -647,7 +647,38 @@ func addTestManifest(repo reference.Named, reference string, mediatype string, c
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func addTestManifestWithoutDigestHeader(repo reference.Named, reference string, mediatype string, content []byte, m *testutil.RequestResponseMap) {
|
||||||
|
*m = append(*m, testutil.RequestResponseMapping{
|
||||||
|
Request: testutil.Request{
|
||||||
|
Method: "GET",
|
||||||
|
Route: "/v2/" + repo.Name() + "/manifests/" + reference,
|
||||||
|
},
|
||||||
|
Response: testutil.Response{
|
||||||
|
StatusCode: http.StatusOK,
|
||||||
|
Body: content,
|
||||||
|
Headers: http.Header(map[string][]string{
|
||||||
|
"Content-Length": {fmt.Sprint(len(content))},
|
||||||
|
"Last-Modified": {time.Now().Add(-1 * time.Second).Format(time.ANSIC)},
|
||||||
|
"Content-Type": {mediatype},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
*m = append(*m, testutil.RequestResponseMapping{
|
||||||
|
Request: testutil.Request{
|
||||||
|
Method: "HEAD",
|
||||||
|
Route: "/v2/" + repo.Name() + "/manifests/" + reference,
|
||||||
|
},
|
||||||
|
Response: testutil.Response{
|
||||||
|
StatusCode: http.StatusOK,
|
||||||
|
Headers: http.Header(map[string][]string{
|
||||||
|
"Content-Length": {fmt.Sprint(len(content))},
|
||||||
|
"Last-Modified": {time.Now().Add(-1 * time.Second).Format(time.ANSIC)},
|
||||||
|
"Content-Type": {mediatype},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkEqualManifest(m1, m2 *schema1.SignedManifest) error {
|
func checkEqualManifest(m1, m2 *schema1.SignedManifest) error {
|
||||||
|
@ -994,6 +1025,36 @@ func TestObtainsErrorForMissingTag(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestObtainsManifestForTagWithoutHeaders(t *testing.T) {
|
||||||
|
repo, _ := reference.WithName("test.example.com/repo")
|
||||||
|
|
||||||
|
var m testutil.RequestResponseMap
|
||||||
|
m1, dgst, _ := newRandomSchemaV1Manifest(repo, "latest", 6)
|
||||||
|
_, pl, err := m1.Payload()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
addTestManifestWithoutDigestHeader(repo, "1.0.0", schema1.MediaTypeSignedManifest, pl, &m)
|
||||||
|
|
||||||
|
e, c := testServer(m)
|
||||||
|
defer c()
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
r, err := NewRepository(ctx, repo, e, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tagService := r.Tags(ctx)
|
||||||
|
|
||||||
|
desc, err := tagService.Get(ctx, "1.0.0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected no error")
|
||||||
|
}
|
||||||
|
if desc.Digest != dgst {
|
||||||
|
t.Fatalf("Unexpected digest")
|
||||||
|
}
|
||||||
|
}
|
||||||
func TestManifestTagsPaginated(t *testing.T) {
|
func TestManifestTagsPaginated(t *testing.T) {
|
||||||
s := httptest.NewServer(http.NotFoundHandler())
|
s := httptest.NewServer(http.NotFoundHandler())
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
Loading…
Reference in a new issue