package handler import ( "bytes" "fmt" "github.com/loveuer/nf" "github.com/sirupsen/logrus" "io" "net/http" "nf-repo/internal/interfaces" "nf-repo/internal/model" "nf-repo/internal/util/rerr" "strings" ) func handleManifest(ctx *nf.Ctx, m interfaces.ManifestHandler) error { elem := strings.Split(ctx.Path(), "/") elem = elem[1:] target := elem[len(elem)-1] repo := strings.Join(elem[1:len(elem)-2], "/") logrus. WithField("handler", "handleManifest"). WithField("path", ctx.Path()). WithField("method", ctx.Method()). WithField("repo", repo). WithField("target", target). Debug() switch ctx.Method() { case http.MethodGet: var ( err error reader io.ReadCloser contentType string re *rerr.RepositoryError bs []byte ) if reader, contentType, re = m.Get(ctx.Request.Context(), repo, target); re != nil { return rerr.Error(ctx, re) } if bs, err = io.ReadAll(reader); err != nil { return rerr.Error(ctx, &rerr.RepositoryError{ Status: http.StatusInternalServerError, Code: "INTERNAL_SERVER_ERROR", Message: err.Error(), }) } h, _, _ := model.SHA256(bytes.NewReader(bs)) ctx.Set("Docker-Content-Digest", h.String()) ctx.Set("Content-Type", contentType) ctx.Set("Content-Length", fmt.Sprint(len(bs))) ctx.Status(http.StatusOK) _, err = ctx.Write(bs) return err case http.MethodHead: var ( err error reader io.ReadCloser contentType string re *rerr.RepositoryError bs []byte ) if reader, contentType, re = m.Get(ctx.Request.Context(), repo, target); re != nil { return rerr.Error(ctx, re) } if bs, err = io.ReadAll(reader); err != nil { return rerr.Error(ctx, &rerr.RepositoryError{ Status: http.StatusInternalServerError, Code: "INTERNAL_SERVER_ERROR", Message: err.Error(), }) } h, _, _ := model.SHA256(bytes.NewReader(bs)) ctx.Set("Docker-Content-Digest", h.String()) ctx.Set("Content-Type", contentType) ctx.Set("Content-Length", fmt.Sprint(len(bs))) return ctx.SendStatus(http.StatusOK) case http.MethodPut: var ( err error buf = &bytes.Buffer{} hash model.Hash ) if _, err = io.Copy(buf, ctx.Request.Body); err != nil { return rerr.Error(ctx, rerr.ErrInternal(err)) } if hash, _, err = model.SHA256(bytes.NewReader(buf.Bytes())); err != nil { return rerr.Error(ctx, rerr.ErrInternal(err)) } digest := hash.String() mf := model.RepoSimpleManifest{ Blob: buf.Bytes(), ContentType: ctx.Get("Content-Type"), } logrus. WithField("handler", "handleManifest"). WithField("path", ctx.Path()). WithField("method", ctx.Method()). WithField("repo", repo). WithField("target", target). WithField("digest", digest). WithField("content-type", ctx.Get("Content-Type")). WithField("content", buf.String()). Debug() if err := m.Put(ctx.Request.Context(), repo, target, digest, &mf); err != nil { return rerr.Error(ctx, err) } ctx.Set("Docker-Content-Digest", digest) return ctx.SendStatus(http.StatusCreated) case http.MethodDelete: return ctx.SendStatus(http.StatusAccepted) default: return rerr.Error(ctx, &rerr.RepositoryError{ Status: http.StatusBadRequest, Code: "METHOD_UNKNOWN", Message: "We don't understand your method + url", }) } }