Files
pages/internal/adminapi/blobs.go
T
2026-08-15 07:13:00 +00:00

40 lines
1.3 KiB
Go

package adminapi
import (
"net/http"
"github.com/iceBear67/simplepages/api"
"github.com/iceBear67/simplepages/internal/cas"
"github.com/iceBear67/simplepages/internal/httpx"
)
// putBlob handles PUT /api/v1/blobs/{digest}.
//
// Blobs are global rather than per-project because the store deduplicates
// across projects, so any authenticated key may upload one — but only content
// some manifest already declared, and only bytes that really hash to the digest
// in the URL. Both checks live in deploy.Service and cas.Store; the digest here
// is a claim until then.
//
// The route is deliberately not owner-guarded: there is no project in the path
// to guard against. What a caller can do with it is bounded by the manifest
// requirement, and the resulting cross-project existence oracle is the known,
// documented trade-off of shared deduplication.
func (s *Server) putBlob(w http.ResponseWriter, r *http.Request) error {
digest, err := cas.ParseDigest(r.PathValue("digest"))
if err != nil {
return api.Errorf(api.CodeBadRequest, "%s", err)
}
size, stored, err := s.Deploy.Upload(r.Context(), digest, r.Body)
if err != nil {
return err
}
status := http.StatusOK // already had it
if stored {
status = http.StatusCreated
}
httpx.WriteJSON(w, status, api.BlobResponse{Digest: digest.String(), Size: size})
return nil
}