Do not write manifests on HEAD requests (#4286)

This commit is contained in:
João Pereira 2024-02-29 07:52:56 +00:00 committed by GitHub
commit 6a568c100f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 60 additions and 0 deletions

View file

@ -1709,6 +1709,33 @@ func testManifestAPISchema2(t *testing.T, env *testEnv, imageName reference.Name
// ------------------ // ------------------
// Fetch by tag name // Fetch by tag name
// HEAD requests should not contain a body
headReq, err := http.NewRequest(http.MethodHead, manifestURL, nil)
if err != nil {
t.Fatalf("Error constructing request: %s", err)
}
headResp, err := http.DefaultClient.Do(headReq)
if err != nil {
t.Fatalf("unexpected error head manifest: %v", err)
}
defer headResp.Body.Close()
checkResponse(t, "head uploaded manifest", headResp, http.StatusOK)
checkHeaders(t, headResp, http.Header{
"Docker-Content-Digest": []string{dgst.String()},
"ETag": []string{fmt.Sprintf(`"%s"`, dgst)},
})
headBody, err := io.ReadAll(headResp.Body)
if err != nil {
t.Fatalf("reading body for head manifest: %v", err)
}
if len(headBody) > 0 {
t.Fatalf("unexpected body length for head manifest: %d", len(headBody))
}
req, err := http.NewRequest(http.MethodGet, manifestURL, nil) req, err := http.NewRequest(http.MethodGet, manifestURL, nil)
if err != nil { if err != nil {
t.Fatalf("Error constructing request: %s", err) t.Fatalf("Error constructing request: %s", err)
@ -1744,6 +1771,32 @@ func testManifestAPISchema2(t *testing.T, env *testEnv, imageName reference.Name
// --------------- // ---------------
// Fetch by digest // Fetch by digest
// HEAD requests should not contain a body
headReq, err = http.NewRequest(http.MethodHead, manifestDigestURL, nil)
if err != nil {
t.Fatalf("Error constructing request: %s", err)
}
headResp, err = http.DefaultClient.Do(headReq)
if err != nil {
t.Fatalf("unexpected error head manifest: %v", err)
}
defer headResp.Body.Close()
checkResponse(t, "head uploaded manifest by digest", headResp, http.StatusOK)
checkHeaders(t, headResp, http.Header{
"Docker-Content-Digest": []string{dgst.String()},
"ETag": []string{fmt.Sprintf(`"%s"`, dgst)},
})
headBody, err = io.ReadAll(headResp.Body)
if err != nil {
t.Fatalf("reading body for head manifest by digest: %v", err)
}
if len(headBody) > 0 {
t.Fatalf("unexpected body length for head manifest: %d", len(headBody))
}
req, err = http.NewRequest(http.MethodGet, manifestDigestURL, nil) req, err = http.NewRequest(http.MethodGet, manifestDigestURL, nil)
if err != nil { if err != nil {
t.Fatalf("Error constructing request: %s", err) t.Fatalf("Error constructing request: %s", err)
@ -2543,6 +2596,8 @@ func maybeDumpResponse(t *testing.T, resp *http.Response) {
// test will fail. If a passed in header value is "*", any non-zero value will // test will fail. If a passed in header value is "*", any non-zero value will
// suffice as a match. // suffice as a match.
func checkHeaders(t *testing.T, resp *http.Response, headers http.Header) { func checkHeaders(t *testing.T, resp *http.Response, headers http.Header) {
t.Helper()
for k, vs := range headers { for k, vs := range headers {
if resp.Header.Get(k) == "" { if resp.Header.Get(k) == "" {
t.Fatalf("response missing header %q", k) t.Fatalf("response missing header %q", k)

View file

@ -212,6 +212,11 @@ func (imh *manifestHandler) GetManifest(w http.ResponseWriter, r *http.Request)
w.Header().Set("Content-Length", fmt.Sprint(len(p))) w.Header().Set("Content-Length", fmt.Sprint(len(p)))
w.Header().Set("Docker-Content-Digest", imh.Digest.String()) w.Header().Set("Docker-Content-Digest", imh.Digest.String())
w.Header().Set("Etag", fmt.Sprintf(`"%s"`, imh.Digest)) w.Header().Set("Etag", fmt.Sprintf(`"%s"`, imh.Digest))
if r.Method == http.MethodHead {
return
}
if _, err := w.Write(p); err != nil { if _, err := w.Write(p); err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
} }