Add Etag header for manifests.
Return 304 (Not Modified) if retrieved with If-None-Match header Signed-off-by: Richard Scothern <richard.scothern@gmail.com>master
							parent
							
								
									d2ca423500
								
							
						
					
					
						commit
						1bc740b0d5
					
				|  | @ -449,6 +449,7 @@ func TestManifestAPI(t *testing.T) { | |||
| 	checkResponse(t, "fetching uploaded manifest", resp, http.StatusOK) | ||||
| 	checkHeaders(t, resp, http.Header{ | ||||
| 		"Docker-Content-Digest": []string{dgst.String()}, | ||||
| 		"ETag":                  []string{dgst.String()}, | ||||
| 	}) | ||||
| 
 | ||||
| 	var fetchedManifest manifest.SignedManifest | ||||
|  | @ -470,6 +471,7 @@ func TestManifestAPI(t *testing.T) { | |||
| 	checkResponse(t, "fetching uploaded manifest", resp, http.StatusOK) | ||||
| 	checkHeaders(t, resp, http.Header{ | ||||
| 		"Docker-Content-Digest": []string{dgst.String()}, | ||||
| 		"ETag":                  []string{dgst.String()}, | ||||
| 	}) | ||||
| 
 | ||||
| 	var fetchedManifestByDigest manifest.SignedManifest | ||||
|  | @ -482,6 +484,33 @@ func TestManifestAPI(t *testing.T) { | |||
| 		t.Fatalf("manifests do not match") | ||||
| 	} | ||||
| 
 | ||||
| 	// Get by name with etag, gives 304
 | ||||
| 	etag := resp.Header.Get("Etag") | ||||
| 	req, err := http.NewRequest("GET", manifestURL, nil) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("Error constructing request: %s", err) | ||||
| 	} | ||||
| 	req.Header.Set("If-None-Match", etag) | ||||
| 	resp, err = http.DefaultClient.Do(req) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("Error constructing request: %s", err) | ||||
| 	} | ||||
| 
 | ||||
| 	checkResponse(t, "fetching layer with etag", resp, http.StatusNotModified) | ||||
| 
 | ||||
| 	// Get by digest with etag, gives 304
 | ||||
| 	req, err = http.NewRequest("GET", manifestDigestURL, nil) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("Error constructing request: %s", err) | ||||
| 	} | ||||
| 	req.Header.Set("If-None-Match", etag) | ||||
| 	resp, err = http.DefaultClient.Do(req) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("Error constructing request: %s", err) | ||||
| 	} | ||||
| 
 | ||||
| 	checkResponse(t, "fetching layer with etag", resp, http.StatusNotModified) | ||||
| 
 | ||||
| 	// Ensure that the tag is listed.
 | ||||
| 	resp, err = http.Get(tagsURL) | ||||
| 	if err != nil { | ||||
|  |  | |||
|  | @ -60,6 +60,10 @@ func (imh *imageManifestHandler) GetImageManifest(w http.ResponseWriter, r *http | |||
| 	if imh.Tag != "" { | ||||
| 		sm, err = manifests.GetByTag(imh.Tag) | ||||
| 	} else { | ||||
| 		if etagMatch(r, imh.Digest.String()) { | ||||
| 			w.WriteHeader(http.StatusNotModified) | ||||
| 			return | ||||
| 		} | ||||
| 		sm, err = manifests.Get(imh.Digest) | ||||
| 	} | ||||
| 
 | ||||
|  | @ -75,6 +79,10 @@ func (imh *imageManifestHandler) GetImageManifest(w http.ResponseWriter, r *http | |||
| 			imh.Errors = append(imh.Errors, v2.ErrorCodeDigestInvalid.WithDetail(err)) | ||||
| 			return | ||||
| 		} | ||||
| 		if etagMatch(r, dgst.String()) { | ||||
| 			w.WriteHeader(http.StatusNotModified) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		imh.Digest = dgst | ||||
| 	} | ||||
|  | @ -82,9 +90,19 @@ func (imh *imageManifestHandler) GetImageManifest(w http.ResponseWriter, r *http | |||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| 	w.Header().Set("Content-Length", fmt.Sprint(len(sm.Raw))) | ||||
| 	w.Header().Set("Docker-Content-Digest", imh.Digest.String()) | ||||
| 	w.Header().Set("Etag", imh.Digest.String()) | ||||
| 	w.Write(sm.Raw) | ||||
| } | ||||
| 
 | ||||
| func etagMatch(r *http.Request, etag string) bool { | ||||
| 	for _, headerVal := range r.Header["If-None-Match"] { | ||||
| 		if headerVal == etag { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| // PutImageManifest validates and stores and image in the registry.
 | ||||
| func (imh *imageManifestHandler) PutImageManifest(w http.ResponseWriter, r *http.Request) { | ||||
| 	ctxu.GetLogger(imh).Debug("PutImageManifest") | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue