mirror of
https://gitcode.com/JianFeeeee/webui4frpc.git
synced 2026-09-20 00:47:57 +00:00
fix: 注册 PUT /api/manager/settings 使设置保存生效
server.go NewServeMux 按方法分发到 handleSettingsPut(原仅注册 GET,PUT 静默返回旧值) 新增 TestSettingsPutRoundTrip 回归测试;gofmt 清理历史格式问题
This commit is contained in:
@ -257,8 +257,6 @@ func (h *Handler) handleProfile(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// ---- helpers ----
|
||||
|
||||
|
||||
|
||||
// tailFile returns the last maxBytes bytes of a file.
|
||||
func tailFile(path string, maxBytes int64) (string, error) {
|
||||
info, err := os.Stat(path)
|
||||
@ -280,4 +278,3 @@ func tailFile(path string, maxBytes int64) (string, error) {
|
||||
}
|
||||
return string(buf), nil
|
||||
}
|
||||
|
||||
|
||||
@ -61,7 +61,13 @@ func NewServeMux(h *Handler) (http.Handler, error) {
|
||||
// API routes (basic auth).
|
||||
mux.HandleFunc(apiPrefix+"/status", auth(h.handleStatus))
|
||||
mux.HandleFunc(apiPrefix+"/canvas", auth(h.handleCanvasSave))
|
||||
mux.HandleFunc(apiPrefix+"/settings", auth(h.handleSettingsGet))
|
||||
mux.HandleFunc(apiPrefix+"/settings", auth(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodPut {
|
||||
h.handleSettingsPut(w, r)
|
||||
return
|
||||
}
|
||||
h.handleSettingsGet(w, r)
|
||||
}))
|
||||
mux.HandleFunc(apiPrefix+"/binary/status", auth(h.handleBinaryStatus))
|
||||
mux.HandleFunc(apiPrefix+"/binary/install", auth(h.handleBinaryInstall))
|
||||
|
||||
@ -135,10 +141,10 @@ func (h *Handler) handleStatus(w http.ResponseWriter, r *http.Request) {
|
||||
settings, _ := h.Store.Settings()
|
||||
|
||||
type profileStatus struct {
|
||||
Name string `json:"name"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Status process.Status `json:"process"`
|
||||
HasProc bool `json:"hasProcess"`
|
||||
Name string `json:"name"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Status process.Status `json:"process"`
|
||||
HasProc bool `json:"hasProcess"`
|
||||
Forwards []store.Forward `json:"forwards"`
|
||||
}
|
||||
|
||||
@ -155,7 +161,7 @@ func (h *Handler) handleStatus(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
// Local status: each local plus its forwarding targets and whether each
|
||||
// Local status: each local plus its forwarding targets and whether each
|
||||
// target's worker is healthy (running).
|
||||
type localTargetStatus struct {
|
||||
Remote string `json:"remote"`
|
||||
@ -163,8 +169,8 @@ func (h *Handler) handleStatus(w http.ResponseWriter, r *http.Request) {
|
||||
WorkerState string `json:"workerState"`
|
||||
}
|
||||
type localStatus struct {
|
||||
Local store.Local `json:"local"`
|
||||
Targets []localTargetStatus `json:"targets"`
|
||||
Local store.Local `json:"local"`
|
||||
Targets []localTargetStatus `json:"targets"`
|
||||
}
|
||||
|
||||
localStatuses := make([]localStatus, 0, len(locals))
|
||||
@ -186,13 +192,13 @@ func (h *Handler) handleStatus(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
resp := map[string]any{
|
||||
"version": "0.1.0",
|
||||
"workDir": h.WorkDir,
|
||||
"settings": settings,
|
||||
"services": locals,
|
||||
"remotes": remotes,
|
||||
"binaryPath": binary,
|
||||
"profiles": profiles,
|
||||
"version": "0.1.0",
|
||||
"workDir": h.WorkDir,
|
||||
"settings": settings,
|
||||
"services": locals,
|
||||
"remotes": remotes,
|
||||
"binaryPath": binary,
|
||||
"profiles": profiles,
|
||||
"localStatus": localStatuses,
|
||||
}
|
||||
writeJSON(w, http.StatusOK, resp)
|
||||
|
||||
@ -97,3 +97,44 @@ func TestCanvasRoundTrip(t *testing.T) {
|
||||
t.Fatalf("remotes after reload = %+v", got2.Remotes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSettingsPutRoundTrip(t *testing.T) {
|
||||
_, ts := newTestHandler(t)
|
||||
client := ts.Client()
|
||||
|
||||
// PUT updated settings
|
||||
body := `{"autoStartProfiles":false,"restartOnExit":false,"restartIntervalSeconds":12}`
|
||||
req, _ := http.NewRequest(http.MethodPut, ts.URL+"/api/manager/settings", bytes.NewBufferString(body))
|
||||
req.SetBasicAuth("admin", "pw")
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatalf("PUT settings status = %d, want 200", resp.StatusCode)
|
||||
}
|
||||
|
||||
// Confirm response body reflects saved values
|
||||
var saved store.Settings
|
||||
if err := json.NewDecoder(resp.Body).Decode(&saved); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if saved.AutoStartProfiles || saved.RestartOnExit || saved.RestartIntervalSeconds != 12 {
|
||||
t.Fatalf("saved settings = %+v", saved)
|
||||
}
|
||||
|
||||
// GET again to confirm persistence
|
||||
req2, _ := http.NewRequest(http.MethodGet, ts.URL+"/api/manager/settings", nil)
|
||||
req2.SetBasicAuth("admin", "pw")
|
||||
resp2, err2 := client.Do(req2)
|
||||
if err2 != nil {
|
||||
t.Fatal(err2)
|
||||
}
|
||||
defer resp2.Body.Close()
|
||||
var got store.Settings
|
||||
_ = json.NewDecoder(resp2.Body).Decode(&got)
|
||||
if got.AutoStartProfiles || got.RestartOnExit || got.RestartIntervalSeconds != 12 {
|
||||
t.Fatalf("settings after reload = %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ type Local struct {
|
||||
type Remote struct {
|
||||
Name string `json:"name"`
|
||||
IP string `json:"ip"`
|
||||
Port int `json:"port"` // port to connect to frps
|
||||
Port int `json:"port"` // port to connect to frps
|
||||
Token string `json:"token,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
Enabled bool `json:"enabled"`
|
||||
@ -32,7 +32,7 @@ type Remote struct {
|
||||
|
||||
// Link connects one local to one remote.
|
||||
type Link struct {
|
||||
ID int64 `json:"id,omitempty"`
|
||||
ID int64 `json:"id,omitempty"`
|
||||
Local string `json:"local"`
|
||||
Remote string `json:"remote"`
|
||||
RemotePort int `json:"remotePort"`
|
||||
|
||||
Reference in New Issue
Block a user