diff --git a/Makefile b/Makefile index 97873bc2c..5d6dd96f4 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,7 @@ version/version.go: bin/%: cmd/% FORCE ## build individual binary @echo "$(WHALE) $@${BINARY_SUFFIX}" - @go build -buildmode=pie ${GO_GCFLAGS} ${GO_BUILD_FLAGS} -o $@${BINARY_SUFFIX} ${GO_LDFLAGS} --ldflags '-extldflags "-Wl,-z,now" -s' ${GO_TAGS} ./$< + @go build -ldflags "-s -w" -trimpath -buildmode=pie ${GO_GCFLAGS} ${GO_BUILD_FLAGS} -o $@${BINARY_SUFFIX} ${GO_LDFLAGS} --ldflags '-extldflags "-Wl,-z,now" -s' ${GO_TAGS} ./$< binaries: $(BINARIES) ## build binaries @echo "$(WHALE) $@" diff --git a/registry/handlers/app.go b/registry/handlers/app.go index 301fc9706..0c79b21c5 100644 --- a/registry/handlers/app.go +++ b/registry/handlers/app.go @@ -670,83 +670,97 @@ func (app *App) dispatcher(dispatch dispatchFunc) http.Handler { w.Header().Add(headerName, value) } } - - context := app.context(w, r) + contextLocal := app.context(w, r) defer func() { // Automated error response handling here. Handlers may return their // own errors if they need different behavior (such as range errors // for layer upload). - if context.Errors.Len() > 0 { - _ = errcode.ServeJSON(w, context.Errors) - app.logError(context, context.Errors) - } else if status, ok := context.Value("http.response.status").(int); ok && status >= 200 && status <= 399 { - dcontext.GetResponseLogger(context).Infof("response completed") + if contextLocal.Errors.Len() > 0 { + _ = errcode.ServeJSON(w, contextLocal.Errors) + app.logError(contextLocal, contextLocal.Errors) + } else if status, ok := contextLocal.Value("http.response.status").(int); ok && status >= 200 && status <= 399 { + dcontext.GetResponseLogger(contextLocal).Infof("response completed") } }() - if err := app.authorized(w, r, context); err != nil { - dcontext.GetLogger(context).Warnf("error authorizing context: %v", err) + if err := app.authorized(w, r, contextLocal); err != nil { + dcontext.GetLogger(contextLocal).Warnf("error authorizing context: %v", err) return } // Add username to request logging - context.Context = dcontext.WithLogger(context.Context, dcontext.GetLogger(context.Context, userNameKey)) + contextLocal.Context = dcontext.WithLogger(contextLocal.Context, dcontext.GetLogger(contextLocal.Context, userNameKey)) // sync up context on the request. - r = r.WithContext(context) + r = r.WithContext(contextLocal) if app.nameRequired(r) { - nameRef, err := reference.WithName(getName(context)) + diyRemoteUrlValue := "" + diyRemoteUrlHeader := http.CanonicalHeaderKey("X-Remote-Repo-Url") + diyRemoteUrlHeaders, ok := r.Header[diyRemoteUrlHeader] + cc := context.Background() + if ok { + diyRemoteUrlValue = diyRemoteUrlHeaders[0] + app.Config.Proxy.RemoteURL = diyRemoteUrlValue + cc = context.WithValue(contextLocal, "ProxyRemoteURL", app.Config.Proxy.RemoteURL) + + } + nameRef, err := reference.WithName(getName(contextLocal)) if err != nil { - dcontext.GetLogger(context).Errorf("error parsing reference from context: %v", err) - context.Errors = append(context.Errors, distribution.ErrRepositoryNameInvalid{ - Name: getName(context), + dcontext.GetLogger(contextLocal).Errorf("error parsing reference from context: %v", err) + contextLocal.Errors = append(contextLocal.Errors, distribution.ErrRepositoryNameInvalid{ + Name: getName(contextLocal), Reason: err, }) - if err := errcode.ServeJSON(w, context.Errors); err != nil { - dcontext.GetLogger(context).Errorf("error serving error json: %v (from %v)", err, context.Errors) + if err := errcode.ServeJSON(w, contextLocal.Errors); err != nil { + dcontext.GetLogger(contextLocal).Errorf("error serving error json: %v (from %v)", err, contextLocal.Errors) } return } - repository, err := app.registry.Repository(context, nameRef) + var repository distribution.Repository + if diyRemoteUrlValue != "" { + repository, err = app.registry.Repository(cc, nameRef) + } else { + repository, err = app.registry.Repository(contextLocal, nameRef) + } if err != nil { - dcontext.GetLogger(context).Errorf("error resolving repository: %v", err) + dcontext.GetLogger(contextLocal).Errorf("error resolving repository: %v", err) switch err := err.(type) { case distribution.ErrRepositoryUnknown: - context.Errors = append(context.Errors, errcode.ErrorCodeNameUnknown.WithDetail(err)) + contextLocal.Errors = append(contextLocal.Errors, errcode.ErrorCodeNameUnknown.WithDetail(err)) case distribution.ErrRepositoryNameInvalid: - context.Errors = append(context.Errors, errcode.ErrorCodeNameInvalid.WithDetail(err)) + contextLocal.Errors = append(contextLocal.Errors, errcode.ErrorCodeNameInvalid.WithDetail(err)) case errcode.Error: - context.Errors = append(context.Errors, err) + contextLocal.Errors = append(contextLocal.Errors, err) } - if err := errcode.ServeJSON(w, context.Errors); err != nil { - dcontext.GetLogger(context).Errorf("error serving error json: %v (from %v)", err, context.Errors) + if err := errcode.ServeJSON(w, contextLocal.Errors); err != nil { + dcontext.GetLogger(contextLocal).Errorf("error serving error json: %v (from %v)", err, contextLocal.Errors) } return } // assign and decorate the authorized repository with an event bridge. - context.Repository, context.RepositoryRemover = notifications.Listen( + contextLocal.Repository, contextLocal.RepositoryRemover = notifications.Listen( repository, - context.App.repoRemover, - app.eventBridge(context, r)) + contextLocal.App.repoRemover, + app.eventBridge(contextLocal, r)) - context.Repository, err = applyRepoMiddleware(app, context.Repository, app.Config.Middleware["repository"]) + contextLocal.Repository, err = applyRepoMiddleware(app, contextLocal.Repository, app.Config.Middleware["repository"]) if err != nil { - dcontext.GetLogger(context).Errorf("error initializing repository middleware: %v", err) - context.Errors = append(context.Errors, errcode.ErrorCodeUnknown.WithDetail(err)) + dcontext.GetLogger(contextLocal).Errorf("error initializing repository middleware: %v", err) + contextLocal.Errors = append(contextLocal.Errors, errcode.ErrorCodeUnknown.WithDetail(err)) - if err := errcode.ServeJSON(w, context.Errors); err != nil { - dcontext.GetLogger(context).Errorf("error serving error json: %v (from %v)", err, context.Errors) + if err := errcode.ServeJSON(w, contextLocal.Errors); err != nil { + dcontext.GetLogger(contextLocal).Errorf("error serving error json: %v (from %v)", err, contextLocal.Errors) } return } } - dispatch(context, r).ServeHTTP(w, r) + dispatch(contextLocal, r).ServeHTTP(w, r) }) } diff --git a/registry/proxy/proxyregistry.go b/registry/proxy/proxyregistry.go index d353af3ff..b87f11c7e 100644 --- a/registry/proxy/proxyregistry.go +++ b/registry/proxy/proxyregistry.go @@ -177,8 +177,12 @@ func (pr *proxyingRegistry) Repository(ctx context.Context, name reference.Named if err != nil { return nil, err } - - remoteRepo, err := client.NewRepository(name, pr.remoteURL.String(), tr) + remoteUrl := pr.remoteURL.String() + ctxRemoteUrl := fmt.Sprint(ctx.Value("ProxyRemoteURL")) + if ctxRemoteUrl != "" { + remoteUrl = ctxRemoteUrl + } + remoteRepo, err := client.NewRepository(name, remoteUrl, tr) if err != nil { return nil, err }