package router import ( "net/http" "time" "go.jolheiser.com/gpm" "go.jolheiser.com/gpm/internal/database" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/go-chi/render" "github.com/rs/zerolog/log" ) func New(token, version 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(version, 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(version string, db *database.Database) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { pkgs, err := db.Packages() if err != nil { log.Err(err).Msg("") return } render.JSON(w, r, gpm.Info{ Version: version, NumPackages: len(pkgs), Packages: pkgs, }) } } func getPackage(db *database.Database) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { name := chi.URLParam(r, "name") pkg, err := db.Package(name) if err != nil { w.WriteHeader(http.StatusNotFound) render.JSON(w, r, struct{}{}) return } render.JSON(w, r, 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 } var pkg gpm.Package if err := render.DecodeJSON(req.Body, &pkg); err != nil { res.WriteHeader(http.StatusBadRequest) return } defer req.Body.Close() 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 } var pkg gpm.Package if err := render.DecodeJSON(req.Body, &pkg); err != nil { res.WriteHeader(http.StatusBadRequest) return } defer req.Body.Close() if err := db.RemovePackage(pkg.Name); err != nil { res.WriteHeader(http.StatusInternalServerError) return } res.WriteHeader(http.StatusOK) } }