package oci import ( "errors" "fmt" "io" "net/http" "strconv" "git.wntrmute.dev/mc/mcr/internal/db" "git.wntrmute.dev/mc/mcr/internal/policy" ) func (h *Handler) handleBlobGet(w http.ResponseWriter, r *http.Request, repo, digest string) { if !h.checkPolicy(w, r, policy.ActionPull, repo) { return } repoID, err := h.db.GetRepositoryByName(repo) if err != nil { if errors.Is(err, db.ErrRepoNotFound) { writeOCIError(w, "NAME_UNKNOWN", http.StatusNotFound, fmt.Sprintf("repository %q not found", repo)) return } h.log.Error("blob get: lookup repository", "error", err, "repo", repo) writeOCIError(w, "UNKNOWN", http.StatusInternalServerError, "internal error") return } exists, err := h.db.BlobExistsInRepo(repoID, digest) if err != nil { h.log.Error("blob get: check blob exists in repo", "error", err, "repo", repo, "digest", digest) writeOCIError(w, "UNKNOWN", http.StatusInternalServerError, "internal error") return } if !exists { writeOCIError(w, "BLOB_UNKNOWN", http.StatusNotFound, fmt.Sprintf("blob %q not found in repository", digest)) return } size, err := h.blobs.Stat(digest) if err != nil { h.log.Error("blob get: stat blob in storage", "error", err, "repo", repo, "digest", digest) writeOCIError(w, "BLOB_UNKNOWN", http.StatusNotFound, "blob not found in storage") return } rc, err := h.blobs.Open(digest) if err != nil { h.log.Error("blob get: open blob in storage", "error", err, "repo", repo, "digest", digest) writeOCIError(w, "UNKNOWN", http.StatusInternalServerError, "internal error") return } defer func() { _ = rc.Close() }() w.Header().Set("Content-Type", "application/octet-stream") w.Header().Set("Docker-Content-Digest", digest) w.Header().Set("Content-Length", strconv.FormatInt(size, 10)) w.WriteHeader(http.StatusOK) _, _ = io.Copy(w, rc) } func (h *Handler) handleBlobHead(w http.ResponseWriter, r *http.Request, repo, digest string) { if !h.checkPolicy(w, r, policy.ActionPull, repo) { return } repoID, err := h.db.GetRepositoryByName(repo) if err != nil { if errors.Is(err, db.ErrRepoNotFound) { writeOCIError(w, "NAME_UNKNOWN", http.StatusNotFound, fmt.Sprintf("repository %q not found", repo)) return } h.log.Error("blob head: lookup repository", "error", err, "repo", repo) writeOCIError(w, "UNKNOWN", http.StatusInternalServerError, "internal error") return } exists, err := h.db.BlobExistsInRepo(repoID, digest) if err != nil { h.log.Error("blob head: check blob exists in repo", "error", err, "repo", repo, "digest", digest) writeOCIError(w, "UNKNOWN", http.StatusInternalServerError, "internal error") return } if !exists { writeOCIError(w, "BLOB_UNKNOWN", http.StatusNotFound, fmt.Sprintf("blob %q not found in repository", digest)) return } size, err := h.blobs.Stat(digest) if err != nil { h.log.Error("blob head: stat blob in storage", "error", err, "repo", repo, "digest", digest) writeOCIError(w, "BLOB_UNKNOWN", http.StatusNotFound, "blob not found in storage") return } w.Header().Set("Content-Type", "application/octet-stream") w.Header().Set("Docker-Content-Digest", digest) w.Header().Set("Content-Length", strconv.FormatInt(size, 10)) w.WriteHeader(http.StatusOK) }