Perform HEAD request, fall back to GET

pull/721/head
Scott Dawson 2023-04-21 08:32:29 +10:00
parent 70c1b892ae
commit 5cd202fcef
No known key found for this signature in database
GPG Key ID: D27F63617C60D508
2 changed files with 32 additions and 8 deletions

View File

@ -15,22 +15,24 @@ func (r *Registry) ManifestDigest(repository, reference string) (digest.Digest,
url := r.url("/v2/%s/manifests/%s", repository, reference)
r.Logf("registry.manifest.head url=%s repository=%s reference=%s", url, repository, reference)
req, err := http.NewRequest("GET", url, nil)
// Try HEAD request first because it's free
resp, err := r.request("HEAD", url)
if err != nil {
return "", err
}
req.Header.Set("Accept", strings.Join([]string{manifestv2.MediaTypeManifest, oci.MediaTypeImageIndex, oci.MediaTypeImageManifest}, ","))
resp, err := r.Client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
if hdr := resp.Header.Get("Docker-Content-Digest"); hdr != "" {
return digest.Parse(hdr)
}
// HEAD request didn't return a digest, attempt to fetch digest from body
r.Logf("registry.manifest.get url=%s repository=%s reference=%s", url, repository, reference)
resp, err = r.request("GET", url)
if err != nil {
return "", err
}
defer resp.Body.Close()
// Try to get digest from body instead, should be equal to what would be presented
// in Docker-Content-Digest
body, err := ioutil.ReadAll(resp.Body)
@ -39,3 +41,19 @@ func (r *Registry) ManifestDigest(repository, reference string) (digest.Digest,
}
return digest.FromBytes(body), nil
}
// request performs a request against a url
func (r *Registry) request(method string, url string) (*http.Response, error) {
req, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
req.Header.Set("Accept", strings.Join([]string{manifestv2.MediaTypeManifest, oci.MediaTypeImageIndex, oci.MediaTypeImageManifest}, ","))
resp, err := r.Client.Do(req)
if err != nil {
return nil, err
}
return resp, nil
}

View File

@ -1,7 +1,9 @@
package docker
import (
"bytes"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
@ -24,9 +26,13 @@ func TestGetDigest(t *testing.T) {
}
defer resp.Body.Close()
bodyBytes, _ := ioutil.ReadAll(resp.Body)
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("content-type", "application/vnd.docker.distribution.manifest.v2+json; charset=ISO-8859-1")
io.Copy(w, resp.Body)
// Reset body for additional calls
resp.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
}))
defer ts.Close()