From 708cc327e54c2d2e53a54579054f2c21a4f908a1 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Fri, 18 Mar 2022 05:22:16 +0000 Subject: [PATCH] Working Template CUD --- api.go | 111 ++++++++++++++++++++++++++++++++++++++++------------ template.go | 1 + 2 files changed, 88 insertions(+), 24 deletions(-) diff --git a/api.go b/api.go index da53939..b65e22a 100644 --- a/api.go +++ b/api.go @@ -1,6 +1,7 @@ package main import "encoding/json" +import "fmt" import "log" import "net/http" @@ -10,18 +11,20 @@ import "github.com/gorilla/mux" type API struct { router *mux.Router store *Store + bus *Bus } func NewAPI(storePath string) *API { api := &API{ router: mux.NewRouter(), store: NewStore(storePath), + bus: NewBus(), } - api.router.HandleFunc("/template", api.createTemplate).Methods("POST").Headers("Content-Type", "application/json") + api.router.HandleFunc("/template", jsonOutput(api.createTemplate)).Methods("POST").Headers("Content-Type", "application/json") api.router.HandleFunc("/template/{id}", api.streamTemplate).Methods("GET").Headers("Accept", "text/event-stream") - api.router.HandleFunc("/template/{id}", api.getTemplate).Methods("GET") - api.router.HandleFunc("/template/{id}", api.updateTemplate).Methods("PATCH").Headers("Content-Type", "application/json") + api.router.HandleFunc("/template/{id}", jsonOutput(api.getTemplate)).Methods("GET") + api.router.HandleFunc("/template/{id}", jsonOutput(api.updateTemplate)).Methods("PATCH").Headers("Content-Type", "application/json") return api } @@ -30,38 +33,27 @@ func (api *API) ServeHTTP(w http.ResponseWriter, r *http.Request) { api.router.ServeHTTP(w, r) } -func (api *API) createTemplate(w http.ResponseWriter, r *http.Request) { +func (api *API) createTemplate(r *http.Request) (interface{}, string, int) { log.Printf("createTemplate") - dec := json.NewDecoder(r.Body) - dec.DisallowUnknownFields() - template := NewTemplate() - err := dec.Decode(template) - if err != nil { - http.Error(w, "invalid JSON", http.StatusBadRequest) - return + msg, code := readJson(r, template) + if code != 0 { + return nil, msg, code } template.Id = uuid.NewString() if !template.IsValid() { - http.Error(w, "invalid template", http.StatusBadRequest) - return + return nil, "Invalid template", http.StatusBadRequest } - err = api.store.Write(template) + err := api.store.Write(template) if err != nil { - http.Error(w, "failed to write template", http.StatusInternalServerError) - return + return nil, "Failed to write template", http.StatusInternalServerError } - enc := json.NewEncoder(w) - err = enc.Encode(template) - if err != nil { - http.Error(w, "failed to encode json", http.StatusInternalServerError) - return - } + return template, "", 0 } func (api *API) streamTemplate(w http.ResponseWriter, r *http.Request) { @@ -86,10 +78,81 @@ func (api *API) streamTemplate(w http.ResponseWriter, r *http.Request) { log.Printf("streamTemplate %s end", mux.Vars(r)) } -func (api *API) getTemplate(w http.ResponseWriter, r *http.Request) { +func (api *API) getTemplate(r *http.Request) (interface{}, string, int) { log.Printf("getTemplate %s", mux.Vars(r)) + + template := NewTemplate() + template.Id = mux.Vars(r)["id"] + + err := api.store.Read(template) + if err != nil { + return nil, fmt.Sprintf("Template %s not found", template.Id), http.StatusNotFound + } + + return template, "", 0 } -func (api *API) updateTemplate(w http.ResponseWriter, r *http.Request) { +func (api *API) updateTemplate(r *http.Request) (interface{}, string, int) { log.Printf("updateTemplate %s", mux.Vars(r)) + + patch := NewTemplate() + + msg, code := readJson(r, patch) + if code != 0 { + return nil, msg, code + } + + template := NewTemplate() + template.Id = mux.Vars(r)["id"] + + err := api.store.Read(template) + if err != nil { + return nil, fmt.Sprintf("Template %s not found", template.Id), http.StatusNotFound + } + + if patch.Title != "" { + template.Title = patch.Title + } + + if !template.IsValid() { + return nil, "Invalid template", http.StatusBadRequest + } + + err = api.store.Write(template) + if err != nil { + return nil, "Failed to write template", http.StatusInternalServerError + } + + api.bus.Announce(template) + + return template, "", 0 + +} + +func readJson(r *http.Request, out interface{}) (string, int) { + dec := json.NewDecoder(r.Body) + dec.DisallowUnknownFields() + + err := dec.Decode(out) + if err != nil { + return fmt.Sprintf("Invalid JSON: %s", err), http.StatusBadRequest + } + + return "", 0 +} + +func jsonOutput(wrapped func(*http.Request) (interface{}, string, int)) func(http.ResponseWriter, *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + out, msg, code := wrapped(r) + if code != 0 { + http.Error(w, msg, code) + return + } + + enc := json.NewEncoder(w) + err := enc.Encode(out) + if err != nil { + http.Error(w, fmt.Sprintf("Failed to encode JSON: %s", err), http.StatusInternalServerError) + } + } } diff --git a/template.go b/template.go index 43a119a..a4c80f8 100644 --- a/template.go +++ b/template.go @@ -4,6 +4,7 @@ import "time" type Template struct { Id string `json:"id"` + Title string `json:"title"` Items []*Item `json:"items"` }