package oci import ( "encoding/json" "fmt" "net/http" "strconv" "git.wntrmute.dev/kyle/mcr/internal/policy" ) type catalogResponse struct { Repositories []string `json:"repositories"` } func (h *Handler) handleCatalog(w http.ResponseWriter, r *http.Request) { if !h.checkPolicy(w, r, policy.ActionCatalog, "") { return } n := 0 var err error if nStr := r.URL.Query().Get("n"); nStr != "" { n, err = strconv.Atoi(nStr) if err != nil || n < 0 { writeOCIError(w, "INVALID_PARAMETER", http.StatusBadRequest, "invalid 'n' parameter") return } } last := r.URL.Query().Get("last") if n == 0 { repos, err := h.db.ListRepositoryNames(last, 10000) if err != nil { h.log.Error("catalog: list repository names", "error", err) writeOCIError(w, "UNKNOWN", http.StatusInternalServerError, "internal error") return } if repos == nil { repos = []string{} } w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(catalogResponse{Repositories: repos}) return } repos, err := h.db.ListRepositoryNames(last, n+1) if err != nil { h.log.Error("catalog: list repository names (paginated)", "error", err) writeOCIError(w, "UNKNOWN", http.StatusInternalServerError, "internal error") return } if repos == nil { repos = []string{} } hasMore := len(repos) > n if hasMore { repos = repos[:n] } if hasMore { lastRepo := repos[len(repos)-1] linkURL := fmt.Sprintf("/v2/_catalog?n=%d&last=%s", n, lastRepo) w.Header().Set("Link", fmt.Sprintf(`<%s>; rel="next"`, linkURL)) } w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(catalogResponse{Repositories: repos}) }