package server import ( "encoding/json" "net/http" ) func (s *Server) handleManageRuntimeConfig(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: raw := r.URL.Query().Get("raw") == "1" view := s.cfg.ViewRuntime(!raw) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(view) case http.MethodPut, http.MethodPost, http.MethodPatch: // read raw bytes first to allow both shapes bodyBytes := make([]byte, 0, 4096) buf := make([]byte, 4096) for { n, err := r.Body.Read(buf) if n > 0 { bodyBytes = append(bodyBytes, buf[:n]...) } if err != nil { break } } var patch map[string]string var wrapped struct { Values map[string]string `json:"values"` } if err := json.Unmarshal(bodyBytes, &wrapped); err == nil && wrapped.Values != nil && len(wrapped.Values) > 0 { patch = wrapped.Values } else { // flat map fallback _ = json.Unmarshal(bodyBytes, &patch) } if len(patch) == 0 { http.Error(w, "values required (send {values: {KEY: value}} or flat {KEY: value})", http.StatusBadRequest) return } changed, err := s.cfg.ApplyRuntimePatch(patch) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } if err := s.cfg.SaveRuntime(); err != nil { http.Error(w, "save: "+err.Error(), http.StatusInternalServerError) return } s.ApplyRuntimeConfig() w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]any{"ok": true, "changed": changed, "values": s.cfg.ViewRuntime(false).Values}) default: http.Error(w, "method not allowed", http.StatusMethodNotAllowed) } } func (s *Server) handleManageRuntimeConfigReset(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost && r.Method != http.MethodDelete { http.Error(w, "method not allowed", http.StatusMethodNotAllowed) return } var body struct { Keys []string `json:"keys"` } _ = json.NewDecoder(r.Body).Decode(&body) if len(body.Keys) == 0 { // reset all: clear overrides via ApplyRuntimePatch for each key to trigger revert all := s.cfg.ViewRuntime(false).Values patch := map[string]string{} for k := range all { patch[k] = "" } if _, err := s.cfg.ApplyRuntimePatch(patch); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } } else { patch := map[string]string{} for _, k := range body.Keys { patch[k] = "" } if _, err := s.cfg.ApplyRuntimePatch(patch); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } } if err := s.cfg.SaveRuntime(); err != nil { http.Error(w, "save: "+err.Error(), http.StatusInternalServerError) return } s.ApplyRuntimeConfig() w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]any{"ok": true}) }