mirror of
https://github.com/goharbor/harbor.git
synced 2024-10-03 07:47:54 +02: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)
|
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,
|
// 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
|
// 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 {
|
type controller struct {
|
||||||
blobCtl blob.Controller
|
blobCtl blob.Controller
|
||||||
@ -121,7 +123,7 @@ func (c *controller) UseLocalManifest(ctx context.Context, art lib.ArtifactInfo,
|
|||||||
return dig == a.Digest, nil // digest matches
|
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
|
var man distribution.Manifest
|
||||||
remoteRepo := getRemoteRepo(art)
|
remoteRepo := getRemoteRepo(art)
|
||||||
ref := getReference(art)
|
ref := getReference(art)
|
||||||
@ -166,7 +168,11 @@ func (c *controller) ProxyManifest(ctx context.Context, p *models.Project, art l
|
|||||||
|
|
||||||
return man, nil
|
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) {
|
func (c *controller) ProxyBlob(ctx context.Context, p *models.Project, art lib.ArtifactInfo) (int64, io.ReadCloser, error) {
|
||||||
remoteRepo := getRemoteRepo(art)
|
remoteRepo := getRemoteRepo(art)
|
||||||
log.Debugf("The blob doesn't exist, proxy the request to the target server, url:%v", remoteRepo)
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ManifestGetMiddleware middleware handle request for get manifest
|
// ManifestMiddleware middleware handle request for get or head manifest
|
||||||
func ManifestGetMiddleware() func(http.Handler) http.Handler {
|
func ManifestMiddleware() func(http.Handler) http.Handler {
|
||||||
return middleware.New(func(w http.ResponseWriter, r *http.Request, next http.Handler) {
|
return middleware.New(func(w http.ResponseWriter, r *http.Request, next http.Handler) {
|
||||||
if err := handleManifest(w, r, next); err != nil {
|
if err := handleManifest(w, r, next); err != nil {
|
||||||
httpLib.SendError(w, err)
|
httpLib.SendError(w, err)
|
||||||
@ -115,7 +115,11 @@ func handleManifest(w http.ResponseWriter, r *http.Request, next http.Handler) e
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
log.Debugf("the tag is %v, digest is %v", art.Tag, art.Digest)
|
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 err != nil {
|
||||||
if errors.IsNotFoundErr(err) {
|
if errors.IsNotFoundErr(err) {
|
||||||
return err
|
return err
|
||||||
@ -126,8 +130,8 @@ func handleManifest(w http.ResponseWriter, r *http.Request, next http.Handler) e
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func proxyManifest(ctx context.Context, w http.ResponseWriter, ctl proxy.Controller, p *models.Project, art lib.ArtifactInfo, remote proxy.RemoteInterface) error {
|
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, p, art, remote)
|
man, err := ctl.ProxyManifest(ctx, art, remote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -200,3 +204,16 @@ func DisableBlobAndManifestUploadMiddleware() func(http.Handler) http.Handler {
|
|||||||
return
|
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().
|
root.NewRoute().
|
||||||
Method(http.MethodGet).
|
Method(http.MethodGet).
|
||||||
Path("/*/manifests/:reference").
|
Path("/*/manifests/:reference").
|
||||||
Middleware(repoproxy.ManifestGetMiddleware()).
|
Middleware(repoproxy.ManifestMiddleware()).
|
||||||
Middleware(contenttrust.Middleware()).
|
Middleware(contenttrust.Middleware()).
|
||||||
Middleware(vulnerable.Middleware()).
|
Middleware(vulnerable.Middleware()).
|
||||||
HandlerFunc(getManifest)
|
HandlerFunc(getManifest)
|
||||||
root.NewRoute().
|
root.NewRoute().
|
||||||
Method(http.MethodHead).
|
Method(http.MethodHead).
|
||||||
Path("/*/manifests/:reference").
|
Path("/*/manifests/:reference").
|
||||||
|
Middleware(repoproxy.ManifestMiddleware()).
|
||||||
HandlerFunc(getManifest)
|
HandlerFunc(getManifest)
|
||||||
root.NewRoute().
|
root.NewRoute().
|
||||||
Method(http.MethodDelete).
|
Method(http.MethodDelete).
|
||||||
|
Loading…
Reference in New Issue
Block a user