blob: c59ef2bfc2e66a443c9fd98edb67403bdf1942c3 [file] [log] [blame]
package apprepo
import (
"fmt"
"io"
"net/http"
"github.com/gorilla/mux"
"sigs.k8s.io/yaml"
)
type App interface {
Name() string
Version() string
Reader() (io.ReadCloser, error)
}
type Server struct {
schemeWithHost string
port int
apps []App
}
func NewServer(schemeWithHost string, port int, apps []App) *Server {
return &Server{schemeWithHost, port, apps}
}
func (s *Server) Start() error {
r := mux.NewRouter()
r.Path("/").Methods("GET").HandlerFunc(s.allApps)
r.Path("/app/{name}/{version}.tar.gz").Methods("GET").HandlerFunc(s.app)
http.Handle("/", r)
return http.ListenAndServe(fmt.Sprintf(":%d", s.port), nil)
}
func (s *Server) allApps(w http.ResponseWriter, r *http.Request) {
entries := make(map[string][]map[string]any)
for _, a := range s.apps {
e, ok := entries[a.Name()]
if !ok {
e = make([]map[string]any, 0)
}
e = append(e, map[string]any{
"version": a.Version(),
"urls": []string{fmt.Sprintf("%s/%s/%s.tar.gz", s.schemeWithHost, a.Name(), a.Version())},
})
entries[a.Name()] = e
}
resp := map[string]any{
"apiVersion": "v1",
"entries": entries,
}
b, err := yaml.Marshal(resp)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Write(b)
}
func (s *Server) app(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
name := vars["name"]
version := vars["version"]
for _, a := range s.apps {
if a.Name() == name && a.Version() == version {
r, err := a.Reader()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer r.Close()
io.Copy(w, r)
return
}
}
http.Error(w, "Not found", http.StatusNotFound)
}