pkg/handlers/root.go (72 lines of code) (raw):

// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. package handlers import ( "context" "net/http" "time" "github.com/azure/peerd/pkg/containerd" pcontext "github.com/azure/peerd/pkg/context" "github.com/azure/peerd/pkg/discovery/routing" filesStore "github.com/azure/peerd/pkg/files/store" "github.com/azure/peerd/pkg/handlers/files" v2 "github.com/azure/peerd/pkg/handlers/v2" "github.com/gin-gonic/gin" "github.com/rs/zerolog" ) var fh *files.FilesHandler var v2h *v2.V2Handler // Server creates a new HTTP server. func Handler(ctx context.Context, r routing.Router, containerdStore containerd.Store, fs filesStore.FilesStore) (http.Handler, error) { var err error fh = files.New(ctx, fs) v2h, err = v2.New(ctx, r, containerdStore) if err != nil { return nil, err } engine := newEngine(ctx) registerRoutes(engine, fileHandler, v2Handler) return engine, nil } // newEngine creates a new gin engine. func newEngine(ctx context.Context) *gin.Engine { gin.SetMode(gin.ReleaseMode) engine := gin.New() baseLog := zerolog.Ctx(ctx) engine.Use(func(c *gin.Context) { pc := pcontext.FromContext(c) pcontext.FillCorrelationId(pc) c.Set(pcontext.LoggerCtxKey, baseLog) l := pcontext.Logger(pc) l.Debug().Msg("request start") s := time.Now() c.Next() status := c.Writer.Status() event := l.Info() if status >= 400 && status < 500 { event = l.Warn() } else if status >= 500 { event = l.Error() } if c.Errors != nil { errs := []error{} for _, e := range c.Errors { errs = append(errs, e.Err) } event = event.Errs("error", errs) } event.Dur("duration", time.Duration(time.Since(s).Seconds())).Str("method", c.Request.Method).Int("status", status).Msg("request served") }) engine.Use(gin.Recovery()) return engine } // registerRoutes registers the routes for the HTTP server. func registerRoutes(engine *gin.Engine, f, v gin.HandlerFunc) { engine.HEAD("/blobs/*url", f) engine.GET("/blobs/*url", f) engine.HEAD("/v2", v) engine.GET("/v2", v) engine.HEAD("/v2/*ref", v) engine.GET("/v2/*ref", v) } // fileHandler is a handler function for the /blob API // @Summary Get a blob by URL // @Param url path string true "The URL of the blob" // @Success 200 {string} string "The blob content" // @Failure 404 {string} string "Not Found" // @Router /blobs/{url} [get] func fileHandler(c *gin.Context) { fh.Handle(pcontext.FromContext(c)) } // v2Handler is a handler function for the /v2 API // @Summary Get a manifest or a blob by repository and reference or digest // @Param repo path string true "The repository name" // @Param reference path string false "The reference of the manifest" // @Param digest path string false "The digest of the blob" // @Success 200 {object} map[string]string "The manifest or blob information" // @Failure 404 {string} string "Not Found" // @Router /v2/{repo}/manifests/{reference} [get] // @Router /v2/{repo}/blobs/{digest} [get] func v2Handler(c *gin.Context) { v2h.Handle(pcontext.FromContext(c)) }