From 63cd339f5e51b9240b8a76d551a6a6dafb71d276 Mon Sep 17 00:00:00 2001 From: Alexander Khodyrev Date: Sat, 28 Sep 2024 13:14:15 +0300 Subject: [PATCH] switch to Go 1.22-style routing --- birdtown-visit-counter.go | 80 +++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/birdtown-visit-counter.go b/birdtown-visit-counter.go index e9308a1..9da7010 100644 --- a/birdtown-visit-counter.go +++ b/birdtown-visit-counter.go @@ -46,50 +46,47 @@ func (s *visitsStore) visit(ending string) int { return newVisits } -type visitsHandler struct { - store *visitsStore -} - -func (h *visitsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { +func commonHeaders(w http.ResponseWriter) { // CORS: this is expected to be called from a different domain, // hoops require jumping w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Max-Age", "86400") w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS") w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization") - - w.Header().Set("content-type", "application/json") - - if r.Method == http.MethodPost { - var s string - if err := json.NewDecoder(r.Body).Decode(&s); err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte("cannot parse data")) - return - } - w.WriteHeader(http.StatusOK) - w.Write(([]byte)(strconv.Itoa(h.store.visit(s)))) - return - } - if r.Method == http.MethodGet { - h.store.Lock() - jsonBytes, err := json.Marshal(h.store.m) - h.store.Unlock() - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte("cannot serialize")) - return - } - w.WriteHeader(http.StatusOK) - w.Write(jsonBytes) - return - } - if r.Method == http.MethodOptions { - w.WriteHeader(http.StatusOK) - return - } w.Header().Set("Allow", "POST, GET, OPTIONS") - w.WriteHeader(http.StatusMethodNotAllowed) +} + +func (store *visitsStore) handleOptions(w http.ResponseWriter, r *http.Request) { + commonHeaders(w) + w.WriteHeader(http.StatusOK) +} + +func (store *visitsStore) handlePost(w http.ResponseWriter, r *http.Request) { + commonHeaders(w) + w.Header().Set("content-type", "application/json") + var s string + if err := json.NewDecoder(r.Body).Decode(&s); err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("cannot parse data")) + return + } + w.WriteHeader(http.StatusOK) + w.Write(([]byte)(strconv.Itoa(store.visit(s)))) +} + +func (store *visitsStore) handleGet(w http.ResponseWriter, r *http.Request) { + commonHeaders(w) + w.Header().Set("content-type", "application/json") + store.Lock() + jsonBytes, err := json.Marshal(store.m) + store.Unlock() + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("cannot serialize")) + return + } + w.WriteHeader(http.StatusOK) + w.Write(jsonBytes) } func main() { @@ -104,11 +101,12 @@ func main() { } else { log.Println("initial file", *initialFile, "could not be read, defaulting to empty data") } - store := visitsStore{m: initialVisits, RWMutex: &sync.RWMutex{}} - visitsH := &visitsHandler{store: &store} - http.Handle("/", visitsH) - log.Println("Starting web server...") + http.HandleFunc("GET /", store.handleGet) + http.HandleFunc("POST /", store.handlePost) + http.HandleFunc("OPTIONS /", store.handleOptions) + + log.Println("Starting web server at ", *addr, "...") http.ListenAndServe(*addr, nil) }