package handlers import ( "net/http" "strconv" "strings" "gitea.loveuer.com/loveuer/cluster/internal/registry/storage" "github.com/gin-gonic/gin" ) // GetBlob 获取 blob func GetBlob(store storage.Storage) gin.HandlerFunc { return func(c *gin.Context) { repo := strings.TrimPrefix(c.Param("name"), "/") digest := c.Param("digest") reader, size, err := store.GetBlob(repo, digest) if err != nil { c.JSON(http.StatusNotFound, gin.H{ "errors": []gin.H{ { "code": "BLOB_UNKNOWN", "message": err.Error(), }, }, }) return } defer reader.Close() c.Header("Content-Type", "application/octet-stream") c.Header("Content-Length", strconv.FormatInt(size, 10)) c.Header("Docker-Content-Digest", digest) c.DataFromReader(http.StatusOK, size, "application/octet-stream", reader, nil) } } // HeadBlob 检查 blob 是否存在 func HeadBlob(store storage.Storage) gin.HandlerFunc { return func(c *gin.Context) { repo := c.GetString("repo_name") if repo == "" { repo = strings.TrimPrefix(c.Param("name"), "/") } digest := c.Param("digest") exists, err := store.BlobExists(repo, digest) if err != nil || !exists { c.Status(http.StatusNotFound) return } size, err := store.GetBlobSize(repo, digest) if err != nil { c.Status(http.StatusNotFound) return } c.Header("Content-Length", strconv.FormatInt(size, 10)) c.Header("Docker-Content-Digest", digest) c.Status(http.StatusOK) } }