From 5267455e59306d6dbe0df324ed41f213bb3cae3b Mon Sep 17 00:00:00 2001 From: mae Date: Mon, 9 Mar 2026 18:18:51 -0500 Subject: [PATCH] cmd/pkgserver: add get endpoint --- cmd/pkgserver/api.go | 53 ++++++++++++++++++++++++++++++++++++++++++ cmd/pkgserver/index.go | 12 +++++++--- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/cmd/pkgserver/api.go b/cmd/pkgserver/api.go index 3049604..1c22a27 100644 --- a/cmd/pkgserver/api.go +++ b/cmd/pkgserver/api.go @@ -2,6 +2,8 @@ package main import ( "bytes" + "encoding/json" + "fmt" "io" "net/http" "path" @@ -53,7 +55,58 @@ func serveStatus(index *PackageIndex) func(w http.ResponseWriter, r *http.Reques } } +type GetPayload struct { + Count int `json:"count"` + Values []PackageIndexEntry `json:"values"` +} + +func NewGetPayload(values []*PackageIndexEntry) GetPayload { + count := len(values) + v := make([]PackageIndexEntry, count) + for i, _ := range values { + v[i] = *values[i] + } + return GetPayload{ + Count: count, + Values: v, + } +} + +func serveGet(index *PackageIndex) func(http.ResponseWriter, *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + q := r.URL.Query() + limit, err := strconv.Atoi(q.Get("limit")) + if err != nil || limit > 100 || limit < 1 { + http.Error(w, fmt.Sprintf("limit must be an integer between 1 and 100"), http.StatusBadRequest) + return + } + i, err := strconv.Atoi(q.Get("index")) + if err != nil || i >= len(index.sorts[0]) || i < 0 { + http.Error(w, fmt.Sprintf("index must be an integer between 0 and %d", len(index.sorts[0])-1), http.StatusBadRequest) + return + } + sort, err := strconv.Atoi(q.Get("sort")) + if err != nil || sort >= len(index.sorts) || sort < 0 { + http.Error(w, fmt.Sprintf("sort must be an integer between 0 and %d", len(index.sorts)-1), http.StatusBadRequest) + return + } + values := index.sorts[sort][i:min(i+limit, len(index.sorts[sort]))] + payload := NewGetPayload(values) + w.Header().Set("Content-Type", "application/json; charset=utf-8") + w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") + w.WriteHeader(http.StatusOK) + b, err := json.Marshal(payload) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + _, err = bytes.NewBuffer(b).WriteTo(w) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } +} func apiRoutes(index *PackageIndex) { http.HandleFunc("GET /api/count", serveCount(index)) + http.HandleFunc("GET /api/get", serveGet(index)) http.HandleFunc("GET /api/status/", serveStatus(index)) } diff --git a/cmd/pkgserver/index.go b/cmd/pkgserver/index.go index 46ee713..37c1b05 100644 --- a/cmd/pkgserver/index.go +++ b/cmd/pkgserver/index.go @@ -2,6 +2,7 @@ package main import ( "cmp" + "fmt" "slices" "hakurei.app/internal/pkg" @@ -25,10 +26,11 @@ type PackageIndex struct { type PackageIndexEntry struct { Name string `json:"name"` - Description string `json:"description"` - Website string `json:"website"` + Description string `json:"description,omitempty"` + Website string `json:"website,omitempty"` Version string `json:"version"` - status []byte + Status string `json:"report,omitempty"` + status []byte `json:"-"` } func createPackageIndex(cache *pkg.Cache, report *rosa.Report) (_ *PackageIndex, err error) { @@ -43,16 +45,20 @@ func createPackageIndex(cache *pkg.Cache, report *rosa.Report) (_ *PackageIndex, id := cache.Ident(a) st, n := report.ArtifactOf(id) var status []byte + var statusUrl string if n < 1 { status = nil + statusUrl = "" } else { status = st + statusUrl = fmt.Sprintf("/api/status/%s.log", m.Name) } entry := PackageIndexEntry{ Name: m.Name, Description: m.Description, Website: m.Website, Version: v, + Status: statusUrl, status: status, } work[p] = entry