cmd/pkgserver: embed internal/rosa metadata

This change also cleans up and reduces some unnecessary copies.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
2026-03-11 01:36:54 +09:00
parent fa9bc70b39
commit 887edcbe48
5 changed files with 350 additions and 101 deletions

View File

@@ -8,35 +8,36 @@ import (
"net/http"
"path"
"strconv"
"sync"
"hakurei.app/internal/info"
"hakurei.app/internal/pkg"
"hakurei.app/internal/rosa"
)
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(),
// for lazy initialisation of serveInfo
var (
infoPayload struct {
// Current package count.
Count int `json:"count"`
// Hakurei version, set at link time.
HakureiVersion string `json:"hakurei_version"`
}
infoPayloadOnce sync.Once
)
// serveInfo returns constant system information.
func serveInfo(w http.ResponseWriter, _ *http.Request) {
infoPayloadOnce.Do(func() {
infoPayload.Count = int(rosa.PresetUnexportedStart)
infoPayload.HakureiVersion = info.Version()
})
w.WriteHeader(http.StatusOK)
// TODO(mae): cache entire response if no additional fields are planned
WritePayload(w, infoPayload)
}
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/json; charset=utf-8")
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
WritePayload(w, NewInfoPayload(index))
}
}
func serveStatus(index *PackageIndex) func(w http.ResponseWriter, r *http.Request) {
func (index *packageIndex) serveStatus() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
download := path.Dir(r.URL.Path) == "/status"
if index == nil {
@@ -83,24 +84,7 @@ 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) {
func (index *packageIndex) serveGet() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
q := r.URL.Query()
limit, err := strconv.Atoi(q.Get("limit"))
@@ -119,17 +103,21 @@ func serveGet(index *PackageIndex) func(http.ResponseWriter, *http.Request) {
return
}
values := index.sorts[sort][i:min(i+limit, len(index.sorts[sort]))]
WritePayload(w, NewGetPayload(values))
// TODO(mae): remove count field
WritePayload(w, &struct {
Count int `json:"count"`
Values []*metadata `json:"values"`
}{len(values), values})
}
}
const ApiVersion = "v1"
func apiRoutes(mux *http.ServeMux, index *PackageIndex) {
mux.HandleFunc(fmt.Sprintf("GET /api/%s/info", ApiVersion), serveInfo(index))
mux.HandleFunc(fmt.Sprintf("GET /api/%s/get", ApiVersion), serveGet(index))
mux.HandleFunc(fmt.Sprintf("GET /api/%s/status/", ApiVersion), serveStatus(index))
mux.HandleFunc("GET /status/", serveStatus(index))
func apiRoutes(mux *http.ServeMux, index *packageIndex) {
mux.HandleFunc(fmt.Sprintf("GET /api/%s/info", ApiVersion), serveInfo)
mux.HandleFunc(fmt.Sprintf("GET /api/%s/get", ApiVersion), index.serveGet())
mux.HandleFunc(fmt.Sprintf("GET /api/%s/status/", ApiVersion), index.serveStatus())
mux.HandleFunc("GET /status/", index.serveStatus())
}
func WritePayload(w http.ResponseWriter, payload any) {