From 08b2ba4c252a1f466527a24d16da7d9a90ee9e34 Mon Sep 17 00:00:00 2001 From: Odboy Date: Fri, 20 Feb 2026 21:18:43 +0800 Subject: [PATCH] =?UTF-8?q?refactor(api):=20fetchAllConfigs=20=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E4=BB=8E=20GET=20=E6=94=B9=E4=B8=BA=20POST?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 服务端: 新增 FetchAllRequest 结构体,参数通过 JSON body 传递 - 服务端: 路由从 api.GET 改为 api.POST - Go/Python/Node.js/Java 客户端同步更新为 POST + JSON body - 与 fetchChangedConfigs 接口风格统一,token 不再暴露在 URL 中 --- go-client/client.go | 19 ++++++-- .../odboy/confcenter/ConfigcenterContext.java | 13 ++++-- .../odboy/confcenter/ConfigcenterContext.java | 13 ++++-- nodejs-client/lib/client.js | 15 ++++++- python-client/kenaito_conf/client.py | 18 ++++---- server/cmd/main.go | 4 +- server/internal/handler/config_api.go | 43 ++++++++++++------- 7 files changed, 88 insertions(+), 37 deletions(-) diff --git a/go-client/client.go b/go-client/client.go index c452f2e..1a3838a 100644 --- a/go-client/client.go +++ b/go-client/client.go @@ -1,6 +1,7 @@ package client import ( + "bytes" "encoding/json" "fmt" "io" @@ -107,14 +108,26 @@ func (c *Client) Stop() { } func (c *Client) fetchAll() error { - url := fmt.Sprintf("%s/api/fetchAllConfigs?appName=%s&env=%s&version=%s&ignoreGlobal=%v", - c.config.BaseURL, c.config.AppName, c.config.Env, c.config.Version, c.config.IgnoreGlobal) + url := fmt.Sprintf("%s/api/fetchAllConfigs", c.config.BaseURL) - req, err := http.NewRequest("GET", url, nil) + payload := map[string]interface{}{ + "appName": c.config.AppName, + "env": c.config.Env, + "version": c.config.Version, + "ignoreGlobal": c.config.IgnoreGlobal, + "token": c.config.Token, + } + payloadBytes, err := json.Marshal(payload) if err != nil { return err } + req, err := http.NewRequest("POST", url, bytes.NewReader(payloadBytes)) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/json") + resp, err := c.httpClient.Do(req) if err != nil { return err diff --git a/kenaito-conf-springboot2-client/src/main/java/cn/odboy/confcenter/ConfigcenterContext.java b/kenaito-conf-springboot2-client/src/main/java/cn/odboy/confcenter/ConfigcenterContext.java index 0e0a732..d37e0ee 100644 --- a/kenaito-conf-springboot2-client/src/main/java/cn/odboy/confcenter/ConfigcenterContext.java +++ b/kenaito-conf-springboot2-client/src/main/java/cn/odboy/confcenter/ConfigcenterContext.java @@ -365,11 +365,18 @@ public class ConfigcenterContext { Map result = null; String errorMsg = null; for (String apiBaseUrl : apiBaseUrls) { - String url = buildTokenParameter(String.format("%s/api/fetchAllConfigs?appName=%s&env=%s&version=%s&ignoreGlobal=%s", - apiBaseUrl, app, env, version, ignoreGlobal)); + String url = apiBaseUrl + "/api/fetchAllConfigs"; + Map params = new HashMap<>(); + params.put("appName", app); + params.put("env", env); + params.put("version", version); + params.put("ignoreGlobal", ignoreGlobal); + if (token != null && !token.isEmpty()) { + params.put("token", token); + } logger.info("fetch configs url:{}", url); try { - String jsonString = httpGet(url); + String jsonString = httpPostJson(url, JSON.toJSONString(params)); if (jsonString != null) { result = JSON.parseObject(jsonString, Map.class); if (result.containsKey("code")) { diff --git a/kenaito-conf-springboot3-client/src/main/java/cn/odboy/confcenter/ConfigcenterContext.java b/kenaito-conf-springboot3-client/src/main/java/cn/odboy/confcenter/ConfigcenterContext.java index 8ecb3cb..c27eba7 100644 --- a/kenaito-conf-springboot3-client/src/main/java/cn/odboy/confcenter/ConfigcenterContext.java +++ b/kenaito-conf-springboot3-client/src/main/java/cn/odboy/confcenter/ConfigcenterContext.java @@ -256,12 +256,19 @@ public class ConfigcenterContext { String errorMsg = null; for (String apiBaseUrl : apiBaseUrls) { - String url = buildTokenParameter(String.format("%s/api/fetchAllConfigs?appName=%s&env=%s&version=%s&ignoreGlobal=%s", - apiBaseUrl, app, env, version, ignoreGlobal)); + String url = apiBaseUrl + "/api/fetchAllConfigs"; + Map params = new HashMap<>(); + params.put("appName", app); + params.put("env", env); + params.put("version", version); + params.put("ignoreGlobal", ignoreGlobal); + if (token != null && !token.isEmpty()) { + params.put("token", token); + } System.out.println("fetch configs url:" + url); try { - String jsonString = HttpUtils.get(url); + String jsonString = HttpUtils.postJson(url, objectMapper.writeValueAsString(params)); if (jsonString != null) { result = objectMapper.readValue(jsonString, Map.class); if (result.containsKey("code")) { diff --git a/nodejs-client/lib/client.js b/nodejs-client/lib/client.js index a49ca4a..32da4fe 100644 --- a/nodejs-client/lib/client.js +++ b/nodejs-client/lib/client.js @@ -62,9 +62,20 @@ export class ConfigClient { } async fetchAll() { - const url = `${this.config.baseUrl}/api/fetchAllConfigs?appName=${encodeURIComponent(this.config.appName)}&env=${encodeURIComponent(this.config.env)}&version=${encodeURIComponent(this.config.version)}&ignoreGlobal=${this.config.ignoreGlobal}&token=${encodeURIComponent(this.config.token)}`; + const url = `${this.config.baseUrl}/api/fetchAllConfigs`; + const payload = { + appName: this.config.appName, + env: this.config.env, + version: this.config.version, + ignoreGlobal: this.config.ignoreGlobal, + token: this.config.token, + }; const resp = await fetch(url, { - headers: this.config.token ? { Authorization: `Bearer ${this.config.token}` } : {}, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(payload), signal: AbortSignal.timeout(10000), }); if (!resp.ok) { diff --git a/python-client/kenaito_conf/client.py b/python-client/kenaito_conf/client.py index 24165a4..672b501 100644 --- a/python-client/kenaito_conf/client.py +++ b/python-client/kenaito_conf/client.py @@ -60,15 +60,15 @@ class ConfigClient: self._stop_event.set() def _fetch_all(self) -> None: - url = ( - f"{self._config.base_url}/api/fetchAllConfigs" - f"?appName={self._config.app_name}" - f"&env={self._config.env}" - f"&version={self._config.version}" - f"&ignoreGlobal={str(self._config.ignore_global).lower()}" - f"&token={self._config.token}" - ) - resp = requests.get(url, timeout=10) + url = f"{self._config.base_url}/api/fetchAllConfigs" + payload = { + "appName": self._config.app_name, + "env": self._config.env, + "version": self._config.version, + "ignoreGlobal": self._config.ignore_global, + "token": self._config.token, + } + resp = requests.post(url, json=payload, timeout=10) resp.raise_for_status() data = resp.json() diff --git a/server/cmd/main.go b/server/cmd/main.go index 7cc5cf1..d3da2c0 100644 --- a/server/cmd/main.go +++ b/server/cmd/main.go @@ -112,10 +112,10 @@ func main() { user.POST("/logout", authHandler.Logout) } - // client API routes (no JWT, uses authtoken or open access) + // client API routes (no JWT, uses token or open access) api := r.Group("/api") { - api.GET("/fetchAllConfigs", configApiHandler.FetchAllConfigs) + api.POST("/fetchAllConfigs", configApiHandler.FetchAllConfigs) api.POST("/fetchChangedConfigs", configApiHandler.FetchChangedConfigs) api.GET("/ping", configApiHandler.Ping) } diff --git a/server/internal/handler/config_api.go b/server/internal/handler/config_api.go index 9b5de8e..bcff633 100644 --- a/server/internal/handler/config_api.go +++ b/server/internal/handler/config_api.go @@ -21,28 +21,41 @@ func NewConfigApiHandler(crypto *service.CryptoService, parse *service.ConfigPar return &ConfigApiHandler{cryptoService: crypto, parseService: parse} } -func (h *ConfigApiHandler) FetchAllConfigs(c *gin.Context) { - appName := c.Query("appName") - env := c.Query("env") - version := c.DefaultQuery("version", "latest") - ignoreGlobal := c.DefaultQuery("ignoreGlobal", "false") == "true" - token := c.Query("token") +type FetchAllRequest struct { + AppName string `json:"appName" binding:"required"` + Env string `json:"env" binding:"required"` + Version string `json:"version"` + IgnoreGlobal bool `json:"ignoreGlobal"` + Token string `json:"token"` +} - if appName == "" || env == "" { +func (h *ConfigApiHandler) FetchAllConfigs(c *gin.Context) { + var req FetchAllRequest + if err := c.ShouldBindJSON(&req); err != nil { + c.JSON(http.StatusBadRequest, model.WrapperResponse{Code: 400, Msg: "参数错误"}) + return + } + + version := req.Version + if version == "" { + version = "latest" + } + + if req.AppName == "" || req.Env == "" { c.JSON(http.StatusBadRequest, model.WrapperResponse{Code: 400, Msg: "参数缺失"}) return } // find app by code var app model.Application - has, _ := dao.Engine.Where("code = ? AND enabled = 1", appName).Get(&app) + has, _ := dao.Engine.Where("code = ? AND enabled = 1", req.AppName).Get(&app) if !has { c.JSON(http.StatusOK, model.WrapperResponse{Code: 1001, Msg: "配置不存在"}) return } // validate token if app has token configured - if app.Token != "" && app.Token != token { + if app.Token != "" && app.Token != req.Token { c.JSON(http.StatusForbidden, model.WrapperResponse{Code: 403, Msg: "Token 无效"}) return } @@ -50,10 +63,10 @@ func (h *ConfigApiHandler) FetchAllConfigs(c *gin.Context) { result := make(map[string]interface{}) // load global configs - if !ignoreGlobal && app.GroupId != nil { + if !req.IgnoreGlobal && app.GroupId != nil { var globalConfigs []model.AppConfig dao.Engine.Where("env = ? AND version = ? AND enabled = 1 AND group_id = ? AND (app_id is null OR app_id = 0)", - env, version, *app.GroupId).Find(&globalConfigs) + req.Env, version, *app.GroupId).Find(&globalConfigs) for _, cfg := range globalConfigs { kvMap := h.parseService.ParseConfigToKVMap(&cfg) for k, v := range kvMap { @@ -66,7 +79,7 @@ func (h *ConfigApiHandler) FetchAllConfigs(c *gin.Context) { if app.ParentId != nil { var parentConfigs []model.AppConfig dao.Engine.Where("env = ? AND version = ? AND enabled = 1 AND app_id = ?", - env, version, *app.ParentId).Find(&parentConfigs) + req.Env, version, *app.ParentId).Find(&parentConfigs) for _, cfg := range parentConfigs { kvMap := h.parseService.ParseConfigToKVMap(&cfg) for k, v := range kvMap { @@ -78,7 +91,7 @@ func (h *ConfigApiHandler) FetchAllConfigs(c *gin.Context) { // load app configs var appConfigs []model.AppConfig dao.Engine.Where("env = ? AND version = ? AND enabled = 1 AND app_id = ?", - env, version, app.Id).Find(&appConfigs) + req.Env, version, app.Id).Find(&appConfigs) for _, cfg := range appConfigs { kvMap := h.parseService.ParseConfigToKVMap(&cfg) for k, v := range kvMap { @@ -92,9 +105,9 @@ func (h *ConfigApiHandler) FetchAllConfigs(c *gin.Context) { } // add encryption keys - globalCryptKey := h.cryptoService.GetCryptKey(0, env) + globalCryptKey := h.cryptoService.GetCryptKey(0, req.Env) result["kenaito.config.global-encrypt-secret"] = globalCryptKey - appCryptKey := h.cryptoService.GetCryptKey(app.Id, env) + appCryptKey := h.cryptoService.GetCryptKey(app.Id, req.Env) result["kenaito.config.encrypt-secret"] = appCryptKey result["latest.fetch.timestamp"] = strconv.FormatInt(time.Now().UnixMilli(), 10)