From 760a82f86ee3dd75227ebf02c380be48362a4485 Mon Sep 17 00:00:00 2001 From: NanamiAdmin Date: Mon, 2 Mar 2026 22:43:18 +0800 Subject: [PATCH] feat(instance): refactor modify endpoint to support config types - Change modify endpoint from `/modify/{field}` to `/modify` with POST - Add support for two modification types: configFile and systemConfig - Implement config file parsing using ini package for configFile type - Update database schema to include name in update query - Add comprehensive input validation and error handling - Update documentation to reflect new API changes --- README.md | 78 +++++++++++++++--- database.db | Bin 24576 -> 24576 bytes database.go | 4 +- frpc.go | 232 +++++++++++++++++++++++++++++++++++++--------------- go.mod | 2 + go.sum | 16 ++++ router.go | 10 +-- 7 files changed, 257 insertions(+), 85 deletions(-) diff --git a/README.md b/README.md index 0c55bfd..d90cbdb 100644 --- a/README.md +++ b/README.md @@ -261,12 +261,12 @@ X-Timestamp: 1704067200000 ### 5. Modify frpc Instance -**Endpoint:** `/frpcAct/instanceMgr/modify/{field}` +**Endpoint:** `/frpcAct/instanceMgr/modify` **Method:** POST **Content-Type:** application/json **Auth Required:** Yes (token) -You can modify multiple fields at once: +Modify instance configuration. Supports two modification types: `configFile` (modify frpc config file) and `systemConfig` (modify system-level settings). **Request Headers:** ``` @@ -274,27 +274,83 @@ X-Token: your_token X-Timestamp: 1704067200000 ``` +#### Type 1: Modify Config File (configFile) + +Modify fields in the `[common]` section of the frpc configuration file. Only `[common]` section fields can be modified, `[[proxies]]` sections will not be affected. + **Request Body:** ```json { "instanceName": "my_frpc", - "name": "new_name", - "serverAddr": "192.168.1.1", - "serverPort": "7000", - "auth_method": "token", - "runUser": "www-data", - "bootAtStart": false + "instanceID": "1", + "type": "configFile", + "modifiedData": { + "server_addr": "192.168.1.1", + "server_port": "7000", + "auth_method": "token", + "auth_token": "my_secret_token" + } } ``` +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| instanceName | string | Yes | Current instance name | +| instanceID | string | Yes | Instance ID | +| type | string | Yes | Modification type: `configFile` or `systemConfig` | +| modifiedData | object | Yes | Key-value pairs of fields to modify in `[common]` section | + **Response:** ```json { "success": true, - "message": "instance modified successfully", + "message": "Config file modified successfully", "data": { - "name": "new_name", - "configPath": "./configs/superfrpc_user_new_name.toml" + "instanceName": "my_frpc", + "instanceID": 1, + "configPath": "./configs/superfrpc_user_my_frpc.toml" + } +} +``` + +#### Type 2: Modify System Config (systemConfig) + +Modify system-level settings such as instance name, boot-at-start configuration, and run user. These changes will also update the operating system service configuration. + +**Request Body:** +```json +{ + "instanceName": "my_frpc", + "instanceID": "1", + "type": "systemConfig", + "modifiedData": { + "name": "new_frpc_name", + "bootAtStart": true, + "runUser": "www-data" + } +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| instanceName | string | Yes | Current instance name | +| instanceID | string | Yes | Instance ID | +| type | string | Yes | Modification type: `configFile` or `systemConfig` | +| modifiedData.name | string | No | New instance name (renames config file if changed) | +| modifiedData.bootAtStart | bool | No | Auto-start on system boot | +| modifiedData.runUser | string | No | User to run the frpc instance as | + +**Response:** +```json +{ + "success": true, + "message": "System config modified successfully", + "data": { + "instanceName": "new_frpc_name", + "instanceID": 1, + "configPath": "./configs/superfrpc_user_new_frpc_name.toml", + "bootAtStart": true, + "runUser": "www-data" } } ``` diff --git a/database.db b/database.db index fe97c041dc92dd3171a77116402a2ca401a67ccc..48bc0498ecbd6afbf0e5c970ed1d3a1422f97b1e 100644 GIT binary patch delta 67 zcmZoTz}Rqrae_1>|3n#QM*fWntL+)*Z59;J;Gb;bpDE3fz{btMDXJ_g&LQe+Uy@o} XVrXfkXJ}@jXE@p4Uu*Lte>njFb43yT delta 60 zcmZoTz}Rqrae_1>-$WT_M!t;+tL+&VY!(#I;Gb;bpDDt|DILeg&A=%tFDlL<>T6$; QT3j;O!{2c8BY!yo0Q}7mP5=M^ diff --git a/database.go b/database.go index 4614294..504730a 100644 --- a/database.go +++ b/database.go @@ -316,8 +316,8 @@ func DBRemoveFrpcInstance(userID int, instanceName string) error { } func DBUpdateFrpcInstance(instance FrpcInstance) error { - _, err := frpcDB.Exec("UPDATE frpcInstances SET serverAddr = ?, serverPort = ?, auth_method = ?, bootAtStart = ?, runUser = ?, configPath = ? WHERE id = ?", - instance.ServerAddr, instance.ServerPort, instance.AuthMethod, instance.BootAtStart, instance.RunUser, instance.ConfigPath, instance.ID) + _, err := frpcDB.Exec("UPDATE frpcInstances SET name = ?, serverAddr = ?, serverPort = ?, auth_method = ?, bootAtStart = ?, runUser = ?, configPath = ? WHERE id = ?", + instance.Name, instance.ServerAddr, instance.ServerPort, instance.AuthMethod, instance.BootAtStart, instance.RunUser, instance.ConfigPath, instance.ID) if err != nil { return fmt.Errorf("failed to update frpc instance: %w", err) } diff --git a/frpc.go b/frpc.go index 8c4c3c9..3cde13c 100644 --- a/frpc.go +++ b/frpc.go @@ -13,6 +13,8 @@ import ( "strings" "super-frpc/postLog" "time" + + "gopkg.in/ini.v1" ) type InstanceInfo struct { @@ -307,7 +309,7 @@ func DeleteInstanceHandler(w http.ResponseWriter, r *http.Request) { postLog.Info(fmt.Sprintf("[DeleteInstanceHandler] Instance %s deleted successfully", instanceName)) } -func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request, field string) { +func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Invalid request method: %s", r.Method)) SendErrorResponse(w, http.StatusMethodNotAllowed, "Invalid request method") @@ -335,6 +337,29 @@ func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request, field string) return } + instanceID := getStringFromMap(reqMap, "instanceID") + if instanceID == "" { + SendErrorResponse(w, http.StatusBadRequest, "instanceID is required") + return + } + + modifyType := getStringFromMap(reqMap, "type") + if modifyType == "" { + SendErrorResponse(w, http.StatusBadRequest, "type is required") + return + } + + if modifyType != "configFile" && modifyType != "systemConfig" { // Detect valid modify type + SendErrorResponse(w, http.StatusBadRequest, "type must be 'configFile' or 'systemConfig'") + return + } + + modifiedData, ok := reqMap["modifiedData"].(map[string]interface{}) + if !ok || modifiedData == nil { + SendErrorResponse(w, http.StatusBadRequest, "modifiedData is required and must be an object") + return + } + // 从Header中验证token和timeStamp userID, _, err := ValidateRequestWithHeader(w, r) if err != nil { @@ -356,14 +381,7 @@ func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request, field string) return } - var instance FrpcInstance - // err = frpcDB.QueryRow(` - // SELECT id, userID, name, serverAddr, serverPort, auth_method, bootAtStart, runUser, configPath, createdAt - // FROM frpcInstances WHERE userID = ? AND name = ? - // `, userID, instanceName).Scan( - // &instance.ID, &instance.UserID, &instance.Name, &instance.ServerAddr, &instance.ServerPort, - // &instance.AuthMethod, &instance.BootAtStart, &instance.RunUser, &instance.ConfigPath, &instance.CreatedAt) - instance, err = DBQueryFrpcInstance(userID, instanceName) + instance, err := DBQueryFrpcInstance(userID, instanceName) if err == sql.ErrNoRows { postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] User %d tried to modify a not existed instance: %s", userID, instanceName)) SendErrorResponse(w, http.StatusNotFound, "Instance not found") @@ -375,38 +393,133 @@ func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request, field string) return } + // 验证 instanceID 是否匹配 + if fmt.Sprintf("%d", instance.ID) != instanceID { + SendErrorResponse(w, http.StatusBadRequest, "instanceID does not match instanceName") + return + } + + if modifyType == "configFile" { + handleConfigFileModify(w, instance, modifiedData, user.Username) + } else { + handleSystemConfigModify(w, r, instance, modifiedData, user) + } +} + +func handleConfigFileModify(w http.ResponseWriter, instance FrpcInstance, modifiedData map[string]interface{}, username string) { + configPath := instance.ConfigPath + + // Read current config file content + configContent, err := os.ReadFile(configPath) + if err != nil { + postLog.Error(fmt.Sprintf("[handleConfigFileModify] Failed to read config file %s: %v", configPath, err)) + SendErrorResponse(w, http.StatusInternalServerError, "Failed to read config file") + return + } + + // Parse config file content + updatedConfig, err := updateCommonSection(string(configContent), modifiedData) + if err != nil { + postLog.Error(fmt.Sprintf("[handleConfigFileModify] Failed to update common section: %v", err)) + SendErrorResponse(w, http.StatusInternalServerError, "Failed to update config file") + return + } + + // Write updated config file content back to file + if err := os.WriteFile(configPath, []byte(updatedConfig), 0644); err != nil { + postLog.Error(fmt.Sprintf("[handleConfigFileModify] Failed to write config file %s: %v", configPath, err)) + SendErrorResponse(w, http.StatusInternalServerError, "Failed to write config file") + return + } + + // Update instance fields in database + if v, ok := modifiedData["server_addr"].(string); ok && v != "" { + instance.ServerAddr = v + } + if v, ok := modifiedData["server_port"].(string); ok && v != "" { + instance.ServerPort = v + } + if v, ok := modifiedData["auth_method"].(string); ok && v != "" { + instance.AuthMethod = v + } + + if err := DBUpdateFrpcInstance(instance); err != nil { + postLog.Error(fmt.Sprintf("[handleConfigFileModify] Failed to update instance in database: %v", err)) + SendErrorResponse(w, http.StatusInternalServerError, "Failed to update instance in database") + return + } + + SendSuccessResponse(w, "Config file modified successfully", map[string]interface{}{ + "instanceName": instance.Name, + "instanceID": instance.ID, + "configPath": configPath, + }) + postLog.Info(fmt.Sprintf("[handleConfigFileModify] Config file for instance %s modified successfully", instance.Name)) +} + +func updateCommonSection(configContent string, modifiedData map[string]interface{}) (string, error) { + cfg, err := ini.Load([]byte(configContent)) + if err != nil { + return "", fmt.Errorf("failed to parse config: %w", err) + } + + commonSection := cfg.Section("common") + if commonSection == nil { + return "", fmt.Errorf("common section not found") + } + + for key, value := range modifiedData { + commonSection.Key(key).SetValue(formatConfigValue(value)) + } + + var buf strings.Builder + if _, err := cfg.WriteTo(&buf); err != nil { + return "", fmt.Errorf("failed to write config: %w", err) + } + + return buf.String(), nil +} + +func formatConfigValue(value interface{}) string { + switch v := value.(type) { + case string: + return v + case bool: + return fmt.Sprintf("%t", v) + case float64: + if v == float64(int64(v)) { + return fmt.Sprintf("%d", int64(v)) + } + return fmt.Sprintf("%f", v) + default: + return fmt.Sprintf("%v", v) + } +} + +func handleSystemConfigModify(w http.ResponseWriter, r *http.Request, instance FrpcInstance, modifiedData map[string]interface{}, user *User) { newName := instance.Name - newServerAddr := instance.ServerAddr - newServerPort := instance.ServerPort - newAuthMethod := instance.AuthMethod newRunUser := instance.RunUser newBootAtStart := instance.BootAtStart + oldBootAtStart := instance.BootAtStart - if v, ok := reqMap["name"].(string); ok && v != "" { + if v, ok := modifiedData["name"].(string); ok && v != "" { newName = v } - if v, ok := reqMap["serverAddr"].(string); ok && v != "" { - newServerAddr = v - } - if v, ok := reqMap["serverPort"].(string); ok && v != "" { - newServerPort = v - } - if v, ok := reqMap["auth_method"].(string); ok && v != "" { - newAuthMethod = v - } - if v, ok := reqMap["runUser"].(string); ok && v != "" { + if v, ok := modifiedData["runUser"].(string); ok { newRunUser = v } - if v, ok := reqMap["bootAtStart"].(bool); ok { + if v, ok := modifiedData["bootAtStart"].(bool); ok { newBootAtStart = v } oldConfigPath := instance.ConfigPath var newConfigPath string + + // If instance name or run user changed, need to rename config file if newName != instance.Name || newRunUser != instance.RunUser { configDir, err := GetConfigDir() if err != nil { - postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to get config directory: %v", err)) + postLog.Error(fmt.Sprintf("[handleSystemConfigModify] Failed to get config directory: %v", err)) SendErrorResponse(w, http.StatusInternalServerError, "Failed to get config directory") return } @@ -417,7 +530,7 @@ func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request, field string) if oldConfigPath != newConfigPath { if _, err := os.Stat(oldConfigPath); err == nil { if err := os.Rename(oldConfigPath, newConfigPath); err != nil { - postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to rename config file %s to %s: %v", oldConfigPath, newConfigPath, err)) + postLog.Error(fmt.Sprintf("[handleSystemConfigModify] Failed to rename config file %s to %s: %v", oldConfigPath, newConfigPath, err)) SendErrorResponse(w, http.StatusInternalServerError, "Failed to rename config file") return } @@ -427,55 +540,44 @@ func ModifyInstanceHandler(w http.ResponseWriter, r *http.Request, field string) newConfigPath = oldConfigPath } - info := InstanceInfo{ - Name: newName, - ServerAddr: newServerAddr, - ServerPort: newServerPort, - AuthMethod: newAuthMethod, - RunUser: newRunUser, - } - - configContent := generateFrpcConfig(info) - if err := os.WriteFile(newConfigPath, []byte(configContent), 0644); err != nil { - postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to update config file: %v", err)) - SendErrorResponse(w, http.StatusInternalServerError, "Failed to update config file") - return - } - - // _, err = frpcDB.Exec(` - // UPDATE frpcInstances - // SET name = ?, serverAddr = ?, serverPort = ?, auth_method = ?, bootAtStart = ?, runUser = ?, configPath = ? - // WHERE id = ? - // `, newName, newServerAddr, newServerPort, newAuthMethod, newBootAtStart, newRunUser, newConfigPath, instance.ID) - + // Update instance fields in database instance.Name = newName - instance.ServerAddr = newServerAddr - instance.ServerPort = newServerPort - instance.AuthMethod = newAuthMethod - instance.BootAtStart = newBootAtStart instance.RunUser = newRunUser + instance.BootAtStart = newBootAtStart instance.ConfigPath = newConfigPath - err = DBUpdateFrpcInstance(instance) - if err != nil { - postLog.Error(fmt.Sprintf("[ModifyInstanceHandler] Failed to update instance in database: %v", err)) + + if err := DBUpdateFrpcInstance(instance); err != nil { + postLog.Error(fmt.Sprintf("[handleSystemConfigModify] Failed to update instance in database: %v", err)) SendErrorResponse(w, http.StatusInternalServerError, "Failed to update instance in database") return } - if instance.BootAtStart && !newBootAtStart { - removeBootService(user.Username, instanceName) - } else if !instance.BootAtStart && newBootAtStart { - createBootService(user.Username, newName, newConfigPath, newRunUser) - } else if instance.BootAtStart && newBootAtStart && (instance.Name != newName || instance.RunUser != newRunUser) { - removeBootService(user.Username, instanceName) - createBootService(user.Username, newName, newConfigPath, newRunUser) + // Handle boot service creation and removal + if oldBootAtStart && !newBootAtStart { + if err := removeBootService(user.Username, instance.Name); err != nil { + postLog.Error(fmt.Sprintf("[handleSystemConfigModify] Failed to remove boot service: %v", err)) + } + } else if !oldBootAtStart && newBootAtStart { + if err := createBootService(user.Username, newName, newConfigPath, newRunUser); err != nil { + postLog.Error(fmt.Sprintf("[handleSystemConfigModify] Failed to create boot service: %v", err)) + } + } else if oldBootAtStart && newBootAtStart && (instance.Name != newName || instance.RunUser != newRunUser) { + if err := removeBootService(user.Username, instance.Name); err != nil { + postLog.Error(fmt.Sprintf("[handleSystemConfigModify] Failed to remove old boot service: %v", err)) + } + if err := createBootService(user.Username, newName, newConfigPath, newRunUser); err != nil { + postLog.Error(fmt.Sprintf("[handleSystemConfigModify] Failed to create new boot service: %v", err)) + } } - SendSuccessResponse(w, "Instance modified successfully", map[string]interface{}{ - "name": newName, - "configPath": newConfigPath, + SendSuccessResponse(w, "System config modified successfully", map[string]interface{}{ + "instanceName": newName, + "instanceID": instance.ID, + "configPath": newConfigPath, + "bootAtStart": newBootAtStart, + "runUser": newRunUser, }) - postLog.Info(fmt.Sprintf("[ModifyInstanceHandler] Instance %s modified successfully: configPath=%s, bootAtStart=%v, runUser=%s", newName, newConfigPath, newBootAtStart, newRunUser)) + postLog.Info(fmt.Sprintf("[handleSystemConfigModify] System config for instance %s modified successfully: bootAtStart=%v, runUser=%s", newName, newBootAtStart, newRunUser)) } func ListInstancesHandler(w http.ResponseWriter, r *http.Request) { diff --git a/go.mod b/go.mod index 035103c..75c5dc6 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,9 @@ require ( github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect golang.org/x/sys v0.37.0 // indirect + gopkg.in/ini.v1 v1.67.1 // indirect modernc.org/libc v1.67.6 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.11.0 // indirect + gopkg.in/ini.v1 v1.67.1 // indirect ) diff --git a/go.sum b/go.sum index 28bd8d8..970e0b7 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -8,13 +10,27 @@ github.com/mattn/go-sqlite3 v1.14.34 h1:3NtcvcUnFBPsuRcno8pUtupspG/GM+9nZ88zgJcp github.com/mattn/go-sqlite3 v1.14.34/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.1 h1:tVBILHy0R6e4wkYOn3XmiITt/hEVH4TFMYvAX2Ytz6k= +gopkg.in/ini.v1 v1.67.1/go.mod h1:x/cyOwCgZqOkJoDIJ3c1KNHMo10+nLGAhh+kn3Zizss= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI= modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= diff --git a/router.go b/router.go index be18fac..d0a438e 100644 --- a/router.go +++ b/router.go @@ -47,13 +47,9 @@ func setupRoutes() { return } - if strings.HasPrefix(remainingPath, "modify/") { - parts := strings.SplitN(remainingPath, "/", 2) - if len(parts) == 2 { - field := parts[1] - ModifyInstanceHandler(w, r, field) - return - } + if remainingPath == "modify" { // Handle `/modify` by POST request + ModifyInstanceHandler(w, r) + return } }