package main import ( "encoding/json" "log" "net/http" "regexp" "strconv" "git.huntm.net/wedding/server/guests" ) type guestHandler struct { store guestStore } type guestStore interface { Get() (map[int]guests.Guest, error) Add(id int, guest guests.Guest) error Update(id int, guest guests.Guest) error } var ( guestRe = regexp.MustCompile(`^/guests/*$`) guestIdRe = regexp.MustCompile(`^/guests/([0-9]+)$`) ) func newGuestHandler(s guestStore) *guestHandler { return &guestHandler{ store: s, } } func (h *guestHandler) getGuests(w http.ResponseWriter, _ *http.Request) { guests, err := h.store.Get() if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) } jsonBytes, err := json.Marshal(guests) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) } w.WriteHeader(http.StatusOK) w.Write(jsonBytes) } func (h *guestHandler) createGuest(w http.ResponseWriter, r *http.Request) { var guest guests.Guest err := json.NewDecoder(r.Body).Decode(&guest) defer r.Body.Close() if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } err = h.store.Add(guest.Id, guest) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } w.WriteHeader(http.StatusOK) } func (h *guestHandler) updateGuest(w http.ResponseWriter, r *http.Request) { matches := guestIdRe.FindStringSubmatch(r.URL.Path) if len(matches) < 2 { http.Error(w, "No id found", http.StatusBadRequest) } var guest guests.Guest err := json.NewDecoder(r.Body).Decode(&guest) defer r.Body.Close() if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) } id, err := strconv.Atoi(matches[1]) if err != nil { http.Error(w, "Cannot convert string to integer", http.StatusBadRequest) } err = h.store.Update(id, guest) if err != nil { http.Error(w, "Guest not found", http.StatusBadRequest) } } func (h *guestHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch { case r.Method == http.MethodGet && guestRe.MatchString(r.URL.Path): h.getGuests(w, r) case r.Method == http.MethodPost && guestRe.MatchString(r.URL.Path): h.createGuest(w, r) case r.Method == http.MethodPut && guestIdRe.MatchString(r.URL.Path): h.updateGuest(w, r) } } func main() { store := guests.NewMemStore() guestHandler := newGuestHandler(store) mux := http.NewServeMux() mux.Handle("/guests/", guestHandler) log.Fatal(http.ListenAndServe(":8080", mux)) }