pkg/handlers/v2/handler.go (73 lines of code) (raw):

// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. package v2 import ( "context" "net/http" "path" "time" "github.com/azure/peerd/pkg/containerd" pcontext "github.com/azure/peerd/pkg/context" "github.com/azure/peerd/pkg/discovery/content/registry" "github.com/azure/peerd/pkg/discovery/routing" "github.com/azure/peerd/pkg/metrics" "github.com/azure/peerd/pkg/oci/distribution" ) // V2Handler describes a handler for OCI content. type V2Handler struct { proxy *registry.Mirror registry *containerd.Registry metricsRecorder metrics.Metrics } // Handle handles a request for a file. func (h *V2Handler) Handle(c pcontext.Context) { l := pcontext.Logger(c).With().Bool("p2p", pcontext.IsRequestFromAPeer(c)).Logger() l.Debug().Msg("v2 handler start") s := time.Now() defer func() { dur := time.Since(s) h.metricsRecorder.RecordRequest(c.Request.Method, "oci", dur.Seconds()) l.Debug().Dur("duration", dur).Str("ns", c.GetString(pcontext.NamespaceCtxKey)).Str("ref", c.GetString(pcontext.ReferenceCtxKey)).Str("digest", c.GetString(pcontext.DigestCtxKey)).Msg("v2 handler stop") }() p := path.Clean(c.Request.URL.Path) if p == "/v2" || p == "/v2/" { if c.Request.Method != http.MethodGet && c.Request.Method != http.MethodHead { c.Status(http.StatusNotFound) return } c.Status(http.StatusOK) return } err := h.fill(c) if err != nil { l.Debug().Err(err).Msg("failed to fill context") // nolint c.AbortWithError(http.StatusBadRequest, err) return } if pcontext.IsRequestFromAPeer(c) { h.registry.Handle(c) return } else { h.proxy.Handle(c) return } } // fill fills the context with handler specific information. func (h *V2Handler) fill(c pcontext.Context) error { c.Set("handler", "v2") ns := c.Query("ns") if ns == "" { ns = "docker.io" } c.Set(pcontext.NamespaceCtxKey, ns) ref, dgst, refType, err := distribution.ParsePathComponents(ns, c.Request.URL.Path) if err != nil { return err } c.Set(pcontext.ReferenceCtxKey, ref) c.Set(pcontext.DigestCtxKey, dgst.String()) c.Set(pcontext.RefTypeCtxKey, refType) return nil } // New creates a new OCI content handler. func New(ctx context.Context, router routing.Router, containerdStore containerd.Store) (*V2Handler, error) { return &V2Handler{ proxy: registry.New(ctx, router), registry: containerd.NewRegistry(containerdStore), metricsRecorder: metrics.FromContext(ctx), }, nil }