128 lines
3.1 KiB
Go
128 lines
3.1 KiB
Go
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:
|
|
b := &bytes.Buffer{}
|
|
io.Copy(b, ctx.Request.Body)
|
|
h, _, _ := model.SHA256(bytes.NewReader(b.Bytes()))
|
|
digest := h.String()
|
|
|
|
mf := model.Manifest{
|
|
Blob: b.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", b.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",
|
|
})
|
|
}
|
|
}
|