mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-26 20:26:13 +01:00
Add middleware to proxy HEAD request for proxy cache project
Fixes: #13153, containerd need to head manifest before pull image Signed-off-by: stonezdj <stonezdj@gmail.com>
This commit is contained in:
parent
cdd0eee2d4
commit
0641b300f3
@ -60,7 +60,9 @@ type Controller interface {
|
||||
ProxyBlob(ctx context.Context, p *models.Project, art lib.ArtifactInfo) (int64, io.ReadCloser, error)
|
||||
// ProxyManifest proxy the manifest request to the remote server, p is the proxy project,
|
||||
// art is the ArtifactInfo which includes the tag or digest of the manifest
|
||||
ProxyManifest(ctx context.Context, p *models.Project, art lib.ArtifactInfo, remote RemoteInterface) (distribution.Manifest, error)
|
||||
ProxyManifest(ctx context.Context, art lib.ArtifactInfo, remote RemoteInterface) (distribution.Manifest, error)
|
||||
// HeadManifest send manifest head request to the remote server
|
||||
HeadManifest(ctx context.Context, art lib.ArtifactInfo, remote RemoteInterface) (bool, string, error)
|
||||
}
|
||||
type controller struct {
|
||||
blobCtl blob.Controller
|
||||
@ -121,7 +123,7 @@ func (c *controller) UseLocalManifest(ctx context.Context, art lib.ArtifactInfo,
|
||||
return dig == a.Digest, nil // digest matches
|
||||
}
|
||||
|
||||
func (c *controller) ProxyManifest(ctx context.Context, p *models.Project, art lib.ArtifactInfo, remote RemoteInterface) (distribution.Manifest, error) {
|
||||
func (c *controller) ProxyManifest(ctx context.Context, art lib.ArtifactInfo, remote RemoteInterface) (distribution.Manifest, error) {
|
||||
var man distribution.Manifest
|
||||
remoteRepo := getRemoteRepo(art)
|
||||
ref := getReference(art)
|
||||
@ -166,7 +168,11 @@ func (c *controller) ProxyManifest(ctx context.Context, p *models.Project, art l
|
||||
|
||||
return man, nil
|
||||
}
|
||||
|
||||
func (c *controller) HeadManifest(ctx context.Context, art lib.ArtifactInfo, remote RemoteInterface) (bool, string, error) {
|
||||
remoteRepo := getRemoteRepo(art)
|
||||
ref := getReference(art)
|
||||
return remote.ManifestExist(remoteRepo, ref)
|
||||
}
|
||||
func (c *controller) ProxyBlob(ctx context.Context, p *models.Project, art lib.ArtifactInfo) (int64, io.ReadCloser, error) {
|
||||
remoteRepo := getRemoteRepo(art)
|
||||
log.Debugf("The blob doesn't exist, proxy the request to the target server, url:%v", remoteRepo)
|
||||
|
@ -83,8 +83,8 @@ func preCheck(ctx context.Context) (art lib.ArtifactInfo, p *models.Project, ctl
|
||||
return
|
||||
}
|
||||
|
||||
// ManifestGetMiddleware middleware handle request for get manifest
|
||||
func ManifestGetMiddleware() func(http.Handler) http.Handler {
|
||||
// ManifestMiddleware middleware handle request for get or head manifest
|
||||
func ManifestMiddleware() func(http.Handler) http.Handler {
|
||||
return middleware.New(func(w http.ResponseWriter, r *http.Request, next http.Handler) {
|
||||
if err := handleManifest(w, r, next); err != nil {
|
||||
httpLib.SendError(w, err)
|
||||
@ -115,7 +115,11 @@ func handleManifest(w http.ResponseWriter, r *http.Request, next http.Handler) e
|
||||
return nil
|
||||
}
|
||||
log.Debugf("the tag is %v, digest is %v", art.Tag, art.Digest)
|
||||
err = proxyManifest(ctx, w, proxyCtl, p, art, remote)
|
||||
if r.Method == http.MethodHead {
|
||||
err = proxyManifestHead(ctx, w, proxyCtl, p, art, remote)
|
||||
} else if r.Method == http.MethodGet {
|
||||
err = proxyManifestGet(ctx, w, proxyCtl, p, art, remote)
|
||||
}
|
||||
if err != nil {
|
||||
if errors.IsNotFoundErr(err) {
|
||||
return err
|
||||
@ -126,8 +130,8 @@ func handleManifest(w http.ResponseWriter, r *http.Request, next http.Handler) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func proxyManifest(ctx context.Context, w http.ResponseWriter, ctl proxy.Controller, p *models.Project, art lib.ArtifactInfo, remote proxy.RemoteInterface) error {
|
||||
man, err := ctl.ProxyManifest(ctx, p, art, remote)
|
||||
func proxyManifestGet(ctx context.Context, w http.ResponseWriter, ctl proxy.Controller, p *models.Project, art lib.ArtifactInfo, remote proxy.RemoteInterface) error {
|
||||
man, err := ctl.ProxyManifest(ctx, art, remote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -200,3 +204,16 @@ func DisableBlobAndManifestUploadMiddleware() func(http.Handler) http.Handler {
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
func proxyManifestHead(ctx context.Context, w http.ResponseWriter, ctl proxy.Controller, p *models.Project, art lib.ArtifactInfo, remote proxy.RemoteInterface) error {
|
||||
exist, dig, err := ctl.HeadManifest(ctx, art, remote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exist {
|
||||
return errors.NotFoundError(fmt.Errorf("The tag %v:%v is not found", art.Repository, art.Tag))
|
||||
}
|
||||
w.Header().Set("Docker-Content-Digest", dig)
|
||||
w.Header().Set("Etag", dig)
|
||||
return nil
|
||||
}
|
||||
|
@ -46,13 +46,14 @@ func RegisterRoutes() {
|
||||
root.NewRoute().
|
||||
Method(http.MethodGet).
|
||||
Path("/*/manifests/:reference").
|
||||
Middleware(repoproxy.ManifestGetMiddleware()).
|
||||
Middleware(repoproxy.ManifestMiddleware()).
|
||||
Middleware(contenttrust.Middleware()).
|
||||
Middleware(vulnerable.Middleware()).
|
||||
HandlerFunc(getManifest)
|
||||
root.NewRoute().
|
||||
Method(http.MethodHead).
|
||||
Path("/*/manifests/:reference").
|
||||
Middleware(repoproxy.ManifestMiddleware()).
|
||||
HandlerFunc(getManifest)
|
||||
root.NewRoute().
|
||||
Method(http.MethodDelete).
|
||||
|
Loading…
Reference in New Issue
Block a user