diff --git a/server/server.go b/server/server.go index afa5440..1de8d25 100644 --- a/server/server.go +++ b/server/server.go @@ -18,6 +18,8 @@ import ( "recipe-manager/services/logger" "recipe-manager/services/oauth" "strings" + "sync" + "time" "github.com/go-chi/chi/v5" "github.com/go-chi/cors" @@ -28,6 +30,8 @@ import ( var ( Log = logger.GetInstance() + + python_api_lock sync.Mutex ) func loadConfig(path string) (*config.ServerConfig, error) { @@ -155,6 +159,15 @@ func (s *Server) createHandler() { r.Post("/merge", func(w http.ResponseWriter, r *http.Request) { + // locking + if !pyAPIhandler(w, r) { + Log.Warn("Merge - user tried to access while another user is requesting merge", + zap.String("user", r.Context().Value("user").(*models.User).Name)) + return + } else { + Log.Debug("Merge - user has access", zap.String("user", r.Context().Value("user").(*models.User).Name)) + } + var targetMap map[string]interface{} err := json.NewDecoder(r.Body).Decode(&targetMap) if err != nil { @@ -230,6 +243,7 @@ func (s *Server) createHandler() { Log.Debug("Query param = ", zap.String("query", r.URL.Query().Get("query"))) // param param := r.URL.Query().Get("query") + Log.Debug("Param = ", zap.String("param", param)) var postRequest map[string]interface{} err := json.NewDecoder(r.Body).Decode(&postRequest) @@ -261,9 +275,11 @@ func (s *Server) createHandler() { // log.Println("Log file ext: ", file_ext) default_changelog_path := "cofffeemachineConfig/" + param + "/" + Log.Debug("Default changelog path: ", zap.String("default_changelog_path", default_changelog_path)) changelog_path := default_changelog_path + log_name + file_ext - if strings.Contains(log_name, default_changelog_path) && strings.Contains(log_name, ".json") { + Log.Debug("Changelog path: ", zap.String("changelog_path", changelog_path)) + if strings.Contains(log_name, "cofffeemachineConfig") && strings.Contains(log_name, ".json") { changelog_path = log_name } @@ -301,24 +317,24 @@ func (s *Server) createHandler() { }) - r.Get("/mergelogList", func(w http.ResponseWriter, r *http.Request) { - ch_dir, err := os.ReadDir("cofffeemachineConfig/changelog") - if err != nil { - Log.Error("Error while trying to read dir: ", zap.String("dir", "cofffeemachineConfig/changelog"), zap.Error(err)) - http.Error(w, err.Error(), http.StatusInternalServerError) - } - displayable := make([]string, 0) + // r.Get("/mergelogList", func(w http.ResponseWriter, r *http.Request) { + // ch_dir, err := os.ReadDir("cofffeemachineConfig/changelog") + // if err != nil { + // Log.Error("Error while trying to read dir: ", zap.String("dir", "cofffeemachineConfig/changelog"), zap.Error(err)) + // http.Error(w, err.Error(), http.StatusInternalServerError) + // } + // displayable := make([]string, 0) - for _, file := range ch_dir { - if strings.Contains(file.Name(), ".html") { + // for _, file := range ch_dir { + // if strings.Contains(file.Name(), ".html") { - displayable = append(displayable, file.Name()[:len(file.Name())-len(filepath.Ext(file.Name()))]) - } - } - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - json.NewEncoder(w).Encode(map[string][]string{"dirs": displayable}) - }) + // displayable = append(displayable, file.Name()[:len(file.Name())-len(filepath.Ext(file.Name()))]) + // } + // } + // w.Header().Set("Content-Type", "application/json") + // w.WriteHeader(http.StatusOK) + // json.NewEncoder(w).Encode(map[string][]string{"dirs": displayable}) + // }) r.Get("/listFileInDir/*", func(w http.ResponseWriter, r *http.Request) { @@ -394,3 +410,28 @@ func (s *Server) createHandler() { func (s *Server) Shutdown(ctx context.Context) error { return s.server.Shutdown(ctx) } + +func pyAPIhandler(w http.ResponseWriter, r *http.Request) bool { + timeout := 10 * time.Second + + if !lockThenTimeout(&python_api_lock, timeout) { + http.Error(w, "API is busy", http.StatusServiceUnavailable) + return false + } + defer python_api_lock.Unlock() + return true +} + +func lockThenTimeout(mutex *sync.Mutex, timeout time.Duration) bool { + ch := make(chan struct{}) + go func() { + mutex.Lock() + close(ch) + }() + select { + case <-ch: + return true + case <-time.After(timeout): + return false + } +}