package router import ( "encoding/json" "io" "net/http" "time" "go.jolheiser.com/gpm/database" "go.jolheiser.com/gpm/go-gpm" "github.com/go-chi/chi" "github.com/go-chi/chi/middleware" "go.jolheiser.com/beaver" ) var Version = "develop" func New(token string, db *database.Database) *chi.Mux { r := chi.NewRouter() r.Use(middleware.RedirectSlashes) r.Use(middleware.Recoverer) r.Use(middleware.Timeout(30 * time.Second)) r.Get("/", handleHome(db)) r.Post("/", addUpdatePackage(db, token)) r.Patch("/", addUpdatePackage(db, token)) r.Delete("/", removePackage(db, token)) r.Get("/{name}", getPackage(db)) return r } func handleHome(db *database.Database) func(res http.ResponseWriter, _ *http.Request) { return func(res http.ResponseWriter, _ *http.Request) { pkgs, err := db.Packages() if err != nil { beaver.Error(err) return } status, err := json.Marshal(gpm.Info{ Version: Version, NumPackages: len(pkgs), Packages: pkgs, }) if err != nil { res.WriteHeader(http.StatusInternalServerError) _, _ = res.Write([]byte("{}")) return } _, _ = res.Write(status) } } func getPackage(db *database.Database) func(http.ResponseWriter, *http.Request) { return func(res http.ResponseWriter, req *http.Request) { name := chi.URLParam(req, "name") pkg, err := db.PackageJSON(name) if err != nil { res.WriteHeader(http.StatusNotFound) _, _ = res.Write([]byte("{}")) return } _, _ = res.Write(pkg) } } func addUpdatePackage(db *database.Database, token string) func(http.ResponseWriter, *http.Request) { return func(res http.ResponseWriter, req *http.Request) { if req.Header.Get(gpm.TokenHeader) != token { res.WriteHeader(http.StatusUnauthorized) return } data, err := io.ReadAll(req.Body) if err != nil { res.WriteHeader(http.StatusBadRequest) return } defer req.Body.Close() var pkg gpm.Package if err := json.Unmarshal(data, &pkg); err != nil { res.WriteHeader(http.StatusBadRequest) return } exists, err := db.PackageJSON(pkg.Name) if err != nil { res.WriteHeader(http.StatusInternalServerError) return } switch req.Method { case http.MethodPost: if exists != nil { res.WriteHeader(http.StatusConflict) return } case http.MethodPatch: if exists == nil { res.WriteHeader(http.StatusNotFound) return } } if err := db.PutPackage(pkg); err != nil { res.WriteHeader(http.StatusInternalServerError) return } switch req.Method { case http.MethodPost: res.WriteHeader(http.StatusCreated) case http.MethodPatch: res.WriteHeader(http.StatusOK) } } } func removePackage(db *database.Database, token string) func(http.ResponseWriter, *http.Request) { return func(res http.ResponseWriter, req *http.Request) { if req.Header.Get(gpm.TokenHeader) != token { res.WriteHeader(http.StatusUnauthorized) return } data, err := io.ReadAll(req.Body) if err != nil { res.WriteHeader(http.StatusBadRequest) return } defer req.Body.Close() var pkg gpm.Package if err := json.Unmarshal(data, &pkg); err != nil { res.WriteHeader(http.StatusBadRequest) return } if err := db.RemovePackage(pkg.Name); err != nil { res.WriteHeader(http.StatusInternalServerError) return } res.WriteHeader(http.StatusOK) } }