From 93673cb359a2e5c18de92e136fc82f745d1c8414 Mon Sep 17 00:00:00 2001 From: mae Date: Mon, 9 Mar 2026 23:41:16 -0500 Subject: [PATCH] cmd/pkgserver: api versioning --- cmd/pkgserver/api.go | 56 ++++++++++++++++++++++++++++-------------- cmd/pkgserver/index.go | 2 +- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/cmd/pkgserver/api.go b/cmd/pkgserver/api.go index 1c22a27..8c4ebbb 100644 --- a/cmd/pkgserver/api.go +++ b/cmd/pkgserver/api.go @@ -10,15 +10,29 @@ import ( "strconv" "strings" + "hakurei.app/internal/info" "hakurei.app/internal/rosa" ) -func serveCount(index *PackageIndex) func(http.ResponseWriter, *http.Request) { +type InfoPayload struct { + Count int `json:"count"` + HakureiVersion string `json:"hakurei_version"` +} + +func NewInfoPayload(index *PackageIndex) InfoPayload { + count := len(index.sorts[0]) + return InfoPayload{ + Count: count, + HakureiVersion: info.Version(), + } +} + +func serveInfo(index *PackageIndex) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) - w.Header().Set("Content-Type", "text/plain; charset=utf-8") - count := len(index.names) - w.Write([]byte(strconv.Itoa(count))) + w.Header().Set("Content-Type", "text/json; charset=utf-8") + w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") + WritePayload(w, NewInfoPayload(index)) } } @@ -91,22 +105,26 @@ func serveGet(index *PackageIndex) func(http.ResponseWriter, *http.Request) { 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) - } + WritePayload(w, NewGetPayload(values)) } } + +const ApiVersion = "v1" + 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)) + http.HandleFunc(fmt.Sprintf("GET /api/%s/info", ApiVersion), serveInfo(index)) + http.HandleFunc(fmt.Sprintf("GET /api/%s/get", ApiVersion), serveGet(index)) + http.HandleFunc(fmt.Sprintf("GET /api/%s/status/", ApiVersion), serveStatus(index)) +} + +func WritePayload(w http.ResponseWriter, payload any) { + w.Header().Set("Content-Type", "application/json; charset=utf-8") + w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") + w.Header().Set("Pragma", "no-cache") + w.Header().Set("Expires", "0") + w.WriteHeader(http.StatusOK) + err := json.NewEncoder(w).Encode(payload) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } } diff --git a/cmd/pkgserver/index.go b/cmd/pkgserver/index.go index 37c1b05..29ba371 100644 --- a/cmd/pkgserver/index.go +++ b/cmd/pkgserver/index.go @@ -51,7 +51,7 @@ func createPackageIndex(cache *pkg.Cache, report *rosa.Report) (_ *PackageIndex, statusUrl = "" } else { status = st - statusUrl = fmt.Sprintf("/api/status/%s.log", m.Name) + statusUrl = fmt.Sprintf("/api/%s/status/%s.log", ApiVersion, m.Name) } entry := PackageIndexEntry{ Name: m.Name,