package server import ( "encoding/json" "fmt" "local/game-show/questions/config" "local/game-show/questions/storage" "local/gziphttp" "local/router" dbstorage "local/storage" "net/http" "path/filepath" "strings" ) func (s *Server) Routes() error { routes := []struct { path string method http.HandlerFunc }{ { path: fmt.Sprintf("create"), method: gzip(s.create), }, { path: fmt.Sprintf("delete/%s", router.Wildcard), method: gzip(s.delete), }, { path: fmt.Sprintf("list"), method: gzip(s.list), }, { path: fmt.Sprintf("cat/%s", router.Wildcard), method: gzip(s.cat), }, { path: fmt.Sprintf("check/%s", router.Wildcard), method: gzip(s.check), }, } for _, route := range routes { err := s.Add(route.path, route.method) if err != nil { return err } } return nil } func gzip(foo http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if gziphttp.Can(r) { gz := gziphttp.New(w) defer gz.Close() w = gz } if filepath.Ext(r.URL.Path) == ".css" { w.Header().Set("Content-Type", "text/css; charset=utf-8") } foo(w, r) } } func (s *Server) create(w http.ResponseWriter, r *http.Request) { one, err := readOne(r) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } one.FillIDs() if !one.HasSolution() { http.Error(w, "must have a solution", http.StatusBadRequest) return } if b, err := json.Marshal(one); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } else if err := config.Get().DB.Set(one.ID, b); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } fmt.Fprintf(w, `{"ok":%q}\n`, one.ID) } func (s *Server) delete(w http.ResponseWriter, r *http.Request) { key := key(r) err := config.Get().DB.Set(key, nil) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } fmt.Fprintln(w, "{}") } func (s *Server) list(w http.ResponseWriter, r *http.Request) { keys, err := config.Get().DB.List(nil) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } if err := json.NewEncoder(w).Encode(keys); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } } func (s *Server) cat(w http.ResponseWriter, r *http.Request) { key := key(r) one, err := loadOne(key) if err == dbstorage.ErrNotFound { http.NotFound(w, r) return } else if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } json.NewEncoder(w).Encode(one) } func (s *Server) check(w http.ResponseWriter, r *http.Request) { got, err := readOne(r) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } want, err := loadOne(got.ID) if err == dbstorage.ErrNotFound { http.NotFound(w, r) return } else if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } ok := want.Check(got) fmt.Fprintf(w, `{"ok":%v}`, ok) } func readOne(r *http.Request) (storage.One, error) { key := key(r) var submit storage.One err := json.NewDecoder(r.Body).Decode(&submit) if key != "" { submit.ID = key } return submit, err } func loadOne(id string) (storage.One, error) { b, err := config.Get().DB.Get(id) if err != nil { return storage.One{}, err } var one storage.One err = json.Unmarshal(b, &one) return one, err } func key(r *http.Request) string { index := strings.Index(r.URL.Path[1:], "/") if index < 0 { return "" } return r.URL.Path[index+2:] }