From bdd07954344ac2da23416c80d4c64a59675344eb Mon Sep 17 00:00:00 2001 From: Alex-larget <33240357+Alex-larget@users.noreply.github.com> Date: Wed, 1 Apr 2026 16:19:06 +0800 Subject: [PATCH] fix: ensure compatibility with Go project plugin by adding 'name' parameter - Added 'name' parameter to the data payload in the restart_via_bt_api function across multiple files to ensure compatibility with different versions of the Go project plugin. - Updated comments to clarify the necessity of including both 'project_name' and 'name' parameters for API requests. --- soul-api/devloy.py | 2 + soul-api/docs/master.py | 4 +- soul-api/internal/config/config.go | 80 +++++++++++++++++++----------- soul-api/master.py | 4 +- 4 files changed, 58 insertions(+), 32 deletions(-) diff --git a/soul-api/devloy.py b/soul-api/devloy.py index 70e62359..20d0b891 100644 --- a/soul-api/devloy.py +++ b/soul-api/devloy.py @@ -331,6 +331,7 @@ def restart_via_bt_api(cfg): data = dict(params) data["action"] = action data["project_name"] = name + data["name"] = name r = requests.post(base + "/plugin?name=go_project", data=data, timeout=15, verify=False) if r.status_code != 200: continue @@ -342,6 +343,7 @@ def restart_via_bt_api(cfg): data = dict(params) data["action"] = "start_go_project" data["project_name"] = name + data["name"] = name r = requests.post(base + "/plugin?name=go_project", data=data, timeout=15, verify=False) if r.status_code == 200: j = r.json() if r.headers.get("content-type", "").startswith("application/json") else {} diff --git a/soul-api/docs/master.py b/soul-api/docs/master.py index 59a4cb1f..8ddbe90d 100644 --- a/soul-api/docs/master.py +++ b/soul-api/docs/master.py @@ -218,11 +218,12 @@ def restart_via_bt_api(cfg): # 宝塔 Go 项目插件:先停止再启动,接口以实际面板版本为准 base = url.rstrip("/") params = {"request_time": req_time, "request_token": req_token} - # 常见形式:/plugin?name=go_project,POST 带 action、project_name + # 常见形式:POST 带 action + 项目标识;部分版本只认 project_name,部分只认 name,故同时传 for action in ("stop_go_project", "start_go_project"): data = dict(params) data["action"] = action data["project_name"] = name + data["name"] = name r = requests.post( base + "/plugin?name=go_project", data=data, @@ -240,6 +241,7 @@ def restart_via_bt_api(cfg): data = dict(params) data["action"] = "start_go_project" data["project_name"] = name + data["name"] = name r = requests.post(base + "/plugin?name=go_project", data=data, timeout=15, verify=False) if r.status_code == 200: j = r.json() if r.headers.get("content-type", "").startswith("application/json") else {} diff --git a/soul-api/internal/config/config.go b/soul-api/internal/config/config.go index d82dfaba..04c4abdc 100644 --- a/soul-api/internal/config/config.go +++ b/soul-api/internal/config/config.go @@ -4,6 +4,7 @@ import ( "log" "os" "path/filepath" + "sort" "strconv" "strings" @@ -89,9 +90,28 @@ func SetCurrent(cfg *Config) { current = cfg } // Get 返回当前配置,未设置时返回 nil func Get() *Config { return current } +// mergeUniqueCORSOrigins 将环境变量中的源与 defaultCORSOrigins 合并去重(排序仅便于日志对比)。 +// 避免线上只配了部分域名时完全覆盖默认值,导致漏掉 souladmin 等跨域失败。 +func mergeUniqueCORSOrigins(fromEnv []string) []string { + seen := make(map[string]struct{}) + for _, o := range defaultCORSOrigins { + seen[o] = struct{}{} + } + for _, o := range fromEnv { + if o != "" { + seen[o] = struct{}{} + } + } + out := make([]string, 0, len(seen)) + for o := range seen { + out = append(out, o) + } + sort.Strings(out) + return out +} + // parseCORSOrigins 从环境变量 CORS_ORIGINS 读取(逗号分隔),未设置则用默认值。 -// 注意:线上若设置 CORS_ORIGINS,必须包含管理端 Origin(如 https://souladmin.quwanzhi.com), -// 否则会覆盖 defaultCORSOrigins 且未列出的源会触发浏览器「No Access-Control-Allow-Origin」。 +// 若设置了 CORS_ORIGINS,会与 defaultCORSOrigins 合并去重,避免漏配管理端 Origin。 func parseCORSOrigins() []string { s := os.Getenv("CORS_ORIGINS") if s == "" { @@ -107,7 +127,7 @@ func parseCORSOrigins() []string { if len(origins) == 0 { return defaultCORSOrigins } - return origins + return mergeUniqueCORSOrigins(origins) } // Load 加载配置,端口等从 .env 读取。 @@ -259,33 +279,33 @@ func Load() (*Config, error) { redisURL := strings.TrimSpace(os.Getenv("REDIS_URL")) cfg := &Config{ - Port: port, - Mode: mode, - DBDSN: dsn, - TrustedProxies: []string{"127.0.0.1", "::1"}, - CORSOrigins: parseCORSOrigins(), - Version: version, - BaseURL: baseURL, - CkbLeadAPIKey: ckbLeadAPIKey, - CkbOpenAPIKey: ckbOpenAPIKey, - CkbOpenAccount: ckbOpenAccount, - WechatAppID: wechatAppID, - WechatAppSecret: wechatAppSecret, - WechatMchID: wechatMchID, - WechatMchKey: wechatMchKey, - WechatNotifyURL: wechatNotifyURL, - WechatMiniProgramState: wechatMiniProgramState, - WechatAPIv3Key: wechatAPIv3Key, - WechatCertPath: wechatCertPath, - WechatKeyPath: wechatKeyPath, - WechatSerialNo: wechatSerialNo, - WechatTransferURL: wechatTransferURL, - AdminUsername: adminUsername, - AdminPassword: adminPassword, - AdminSessionSecret: adminSessionSecret, - SyncOrdersIntervalMinutes: syncOrdersInterval, - UploadDir: uploadDir, - RedisURL: redisURL, + Port: port, + Mode: mode, + DBDSN: dsn, + TrustedProxies: []string{"127.0.0.1", "::1"}, + CORSOrigins: parseCORSOrigins(), + Version: version, + BaseURL: baseURL, + CkbLeadAPIKey: ckbLeadAPIKey, + CkbOpenAPIKey: ckbOpenAPIKey, + CkbOpenAccount: ckbOpenAccount, + WechatAppID: wechatAppID, + WechatAppSecret: wechatAppSecret, + WechatMchID: wechatMchID, + WechatMchKey: wechatMchKey, + WechatNotifyURL: wechatNotifyURL, + WechatMiniProgramState: wechatMiniProgramState, + WechatAPIv3Key: wechatAPIv3Key, + WechatCertPath: wechatCertPath, + WechatKeyPath: wechatKeyPath, + WechatSerialNo: wechatSerialNo, + WechatTransferURL: wechatTransferURL, + AdminUsername: adminUsername, + AdminPassword: adminPassword, + AdminSessionSecret: adminSessionSecret, + SyncOrdersIntervalMinutes: syncOrdersInterval, + UploadDir: uploadDir, + RedisURL: redisURL, } // 生产环境(GIN_MODE=release)强制校验敏感配置,禁止使用默认值 diff --git a/soul-api/master.py b/soul-api/master.py index dba70a3a..8ef0b7be 100644 --- a/soul-api/master.py +++ b/soul-api/master.py @@ -220,11 +220,12 @@ def restart_via_bt_api(cfg): # 宝塔 Go 项目插件:先停止再启动,接口以实际面板版本为准 base = url.rstrip("/") params = {"request_time": req_time, "request_token": req_token} - # 常见形式:/plugin?name=go_project,POST 带 action、project_name + # 常见形式:POST 带 action + 项目标识;部分版本只认 project_name,部分只认 name,故同时传 for action in ("stop_go_project", "start_go_project"): data = dict(params) data["action"] = action data["project_name"] = name + data["name"] = name r = requests.post( base + "/plugin?name=go_project", data=data, @@ -242,6 +243,7 @@ def restart_via_bt_api(cfg): data = dict(params) data["action"] = "start_go_project" data["project_name"] = name + data["name"] = name r = requests.post(base + "/plugin?name=go_project", data=data, timeout=15, verify=False) if r.status_code == 200: j = r.json() if r.headers.get("content-type", "").startswith("application/json") else {}