package app import ( "encoding/json" "fmt" "io" "net/http" "strings" ) func handleSmartdnsRuntime(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: writeJSON(w, http.StatusOK, smartDNSRuntimeSnapshot()) case http.MethodPost: var body SmartDNSRuntimeRequest if r.Body != nil { defer r.Body.Close() if err := json.NewDecoder(io.LimitReader(r.Body, 1<<20)).Decode(&body); err != nil && err != io.EOF { http.Error(w, "bad json", http.StatusBadRequest) return } } if body.Enabled == nil { http.Error(w, "enabled is required", http.StatusBadRequest) return } prev := loadSmartDNSRuntimeState(nil) next := prev next.Enabled = *body.Enabled if err := saveSmartDNSRuntimeState(next); err != nil { http.Error(w, "runtime state write error", http.StatusInternalServerError) return } changed, err := applySmartDNSRuntimeConfig(next.Enabled) if err != nil { _ = saveSmartDNSRuntimeState(prev) http.Error(w, "runtime config apply error: "+err.Error(), http.StatusInternalServerError) return } restart := true if body.Restart != nil { restart = *body.Restart } restarted := false msg := "" if restart && smartdnsUnitState() == "active" { res := runSmartdnsUnitAction("restart") restarted = res.OK if !res.OK { msg = "runtime config changed, but smartdns restart failed: " + strings.TrimSpace(res.Message) } } if msg == "" { msg = fmt.Sprintf("smartdns runtime set: enabled=%t changed=%t restarted=%t", next.Enabled, changed, restarted) } appendTraceLineTo(smartdnsLogPath, "smartdns", msg) resp := smartDNSRuntimeSnapshot() resp.Changed = changed resp.Restarted = restarted resp.Message = msg writeJSON(w, http.StatusOK, resp) default: http.Error(w, "method not allowed", http.StatusMethodNotAllowed) } }