in registry/handlers/app.go [1483:1571]
func (app *App) dispatcher(dispatch dispatchFunc) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
for headerName, headerValues := range app.Config.HTTP.Headers {
for _, value := range headerValues {
w.Header().Add(headerName, value)
}
}
ctx := app.context(w, r)
// attach CF-RayID header to context and pass the key to the logger
ctx.Context = dcontext.WithCFRayID(ctx.Context, r)
ctx.Context = dcontext.WithLogger(ctx.Context, dcontext.GetLogger(ctx.Context, dcontext.CFRayIDLogKey))
if err := app.authorized(w, r, ctx); err != nil {
var authErr auth.Challenge
if !errors.As(err, &authErr) {
dcontext.GetLogger(ctx).WithError(err).Warn("error authorizing context")
}
return
}
// Add extra context to request logging
ctx.Context = dcontext.WithLogger(ctx.Context, dcontext.GetLogger(ctx.Context, auth.UserNameKey, auth.UserTypeKey, auth.ResourceProjectPathsKey))
// sync up context on the request.
r = r.WithContext(ctx)
// get all metadata either from the database or from the filesystem
if app.Config.Database.Enabled {
ctx.useDatabase = true
}
if app.nameRequired(r) {
bp, ok := app.registry.Blobs().(distribution.BlobProvider)
if !ok {
err := fmt.Errorf("unable to convert BlobEnumerator into BlobProvider")
dcontext.GetLogger(ctx).Error(err)
ctx.Errors = append(ctx.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
}
ctx.blobProvider = bp
repository, err := app.repositoryFromContext(ctx, w)
if err != nil {
return
}
ctx.queueBridge = app.queueBridge(ctx, r)
// assign and decorate the authorized repository with an event bridge.
ctx.Repository, ctx.RepositoryRemover = notifications.Listen(
repository,
ctx.App.repoRemover,
app.eventBridge(ctx, r),
ctx.useDatabase)
ctx.Repository, err = applyRepoMiddleware(app, ctx.Repository, app.Config.Middleware["repository"])
if err != nil {
dcontext.GetLogger(ctx).Errorf("error initializing repository middleware: %v", err)
ctx.Errors = append(ctx.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
if err := errcode.ServeJSON(w, ctx.Errors); err != nil {
dcontext.GetLogger(ctx).Errorf("error serving error json: %v (from %v)", err, ctx.Errors)
}
return
}
}
if ctx.useDatabase {
if app.redisCache != nil {
ctx.repoCache = datastore.NewCentralRepositoryCache(app.redisCache)
} else {
ctx.repoCache = datastore.NewSingleRepositoryCache()
}
}
dispatch(ctx, r).ServeHTTP(w, r)
// Automated error response handling here. Handlers may return their
// own errors if they need different behavior (such as range errors
// for layer upload).
if ctx.Errors.Len() > 0 {
if err := errcode.ServeJSON(w, ctx.Errors); err != nil {
dcontext.GetLogger(ctx).Errorf("error serving error json: %v (from %v)", err, ctx.Errors)
}
app.logError(ctx, r, ctx.Errors)
}
})
}