refactor(api): fetchAllConfigs 接口从 GET 改为 POST
- 服务端: 新增 FetchAllRequest 结构体,参数通过 JSON body 传递 - 服务端: 路由从 api.GET 改为 api.POST - Go/Python/Node.js/Java 客户端同步更新为 POST + JSON body - 与 fetchChangedConfigs 接口风格统一,token 不再暴露在 URL 中
This commit is contained in:
+16
-3
@@ -1,6 +1,7 @@
|
|||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -107,14 +108,26 @@ func (c *Client) Stop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) fetchAll() error {
|
func (c *Client) fetchAll() error {
|
||||||
url := fmt.Sprintf("%s/api/fetchAllConfigs?appName=%s&env=%s&version=%s&ignoreGlobal=%v",
|
url := fmt.Sprintf("%s/api/fetchAllConfigs", c.config.BaseURL)
|
||||||
c.config.BaseURL, c.config.AppName, c.config.Env, c.config.Version, c.config.IgnoreGlobal)
|
|
||||||
|
|
||||||
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 {
|
if err != nil {
|
||||||
return err
|
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)
|
resp, err := c.httpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
+10
-3
@@ -365,11 +365,18 @@ public class ConfigcenterContext {
|
|||||||
Map<String, Object> result = null;
|
Map<String, Object> result = null;
|
||||||
String errorMsg = null;
|
String errorMsg = null;
|
||||||
for (String apiBaseUrl : apiBaseUrls) {
|
for (String apiBaseUrl : apiBaseUrls) {
|
||||||
String url = buildTokenParameter(String.format("%s/api/fetchAllConfigs?appName=%s&env=%s&version=%s&ignoreGlobal=%s",
|
String url = apiBaseUrl + "/api/fetchAllConfigs";
|
||||||
apiBaseUrl, app, env, version, ignoreGlobal));
|
Map<String, Object> 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);
|
logger.info("fetch configs url:{}", url);
|
||||||
try {
|
try {
|
||||||
String jsonString = httpGet(url);
|
String jsonString = httpPostJson(url, JSON.toJSONString(params));
|
||||||
if (jsonString != null) {
|
if (jsonString != null) {
|
||||||
result = JSON.parseObject(jsonString, Map.class);
|
result = JSON.parseObject(jsonString, Map.class);
|
||||||
if (result.containsKey("code")) {
|
if (result.containsKey("code")) {
|
||||||
|
|||||||
+10
-3
@@ -256,12 +256,19 @@ public class ConfigcenterContext {
|
|||||||
String errorMsg = null;
|
String errorMsg = null;
|
||||||
|
|
||||||
for (String apiBaseUrl : apiBaseUrls) {
|
for (String apiBaseUrl : apiBaseUrls) {
|
||||||
String url = buildTokenParameter(String.format("%s/api/fetchAllConfigs?appName=%s&env=%s&version=%s&ignoreGlobal=%s",
|
String url = apiBaseUrl + "/api/fetchAllConfigs";
|
||||||
apiBaseUrl, app, env, version, ignoreGlobal));
|
Map<String, Object> 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);
|
System.out.println("fetch configs url:" + url);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String jsonString = HttpUtils.get(url);
|
String jsonString = HttpUtils.postJson(url, objectMapper.writeValueAsString(params));
|
||||||
if (jsonString != null) {
|
if (jsonString != null) {
|
||||||
result = objectMapper.readValue(jsonString, Map.class);
|
result = objectMapper.readValue(jsonString, Map.class);
|
||||||
if (result.containsKey("code")) {
|
if (result.containsKey("code")) {
|
||||||
|
|||||||
@@ -62,9 +62,20 @@ export class ConfigClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fetchAll() {
|
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, {
|
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),
|
signal: AbortSignal.timeout(10000),
|
||||||
});
|
});
|
||||||
if (!resp.ok) {
|
if (!resp.ok) {
|
||||||
|
|||||||
@@ -60,15 +60,15 @@ class ConfigClient:
|
|||||||
self._stop_event.set()
|
self._stop_event.set()
|
||||||
|
|
||||||
def _fetch_all(self) -> None:
|
def _fetch_all(self) -> None:
|
||||||
url = (
|
url = f"{self._config.base_url}/api/fetchAllConfigs"
|
||||||
f"{self._config.base_url}/api/fetchAllConfigs"
|
payload = {
|
||||||
f"?appName={self._config.app_name}"
|
"appName": self._config.app_name,
|
||||||
f"&env={self._config.env}"
|
"env": self._config.env,
|
||||||
f"&version={self._config.version}"
|
"version": self._config.version,
|
||||||
f"&ignoreGlobal={str(self._config.ignore_global).lower()}"
|
"ignoreGlobal": self._config.ignore_global,
|
||||||
f"&token={self._config.token}"
|
"token": self._config.token,
|
||||||
)
|
}
|
||||||
resp = requests.get(url, timeout=10)
|
resp = requests.post(url, json=payload, timeout=10)
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
data = resp.json()
|
data = resp.json()
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -112,10 +112,10 @@ func main() {
|
|||||||
user.POST("/logout", authHandler.Logout)
|
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 := r.Group("/api")
|
||||||
{
|
{
|
||||||
api.GET("/fetchAllConfigs", configApiHandler.FetchAllConfigs)
|
api.POST("/fetchAllConfigs", configApiHandler.FetchAllConfigs)
|
||||||
api.POST("/fetchChangedConfigs", configApiHandler.FetchChangedConfigs)
|
api.POST("/fetchChangedConfigs", configApiHandler.FetchChangedConfigs)
|
||||||
api.GET("/ping", configApiHandler.Ping)
|
api.GET("/ping", configApiHandler.Ping)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,28 +21,41 @@ func NewConfigApiHandler(crypto *service.CryptoService, parse *service.ConfigPar
|
|||||||
return &ConfigApiHandler{cryptoService: crypto, parseService: parse}
|
return &ConfigApiHandler{cryptoService: crypto, parseService: parse}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ConfigApiHandler) FetchAllConfigs(c *gin.Context) {
|
type FetchAllRequest struct {
|
||||||
appName := c.Query("appName")
|
AppName string `json:"appName" binding:"required"`
|
||||||
env := c.Query("env")
|
Env string `json:"env" binding:"required"`
|
||||||
version := c.DefaultQuery("version", "latest")
|
Version string `json:"version"`
|
||||||
ignoreGlobal := c.DefaultQuery("ignoreGlobal", "false") == "true"
|
IgnoreGlobal bool `json:"ignoreGlobal"`
|
||||||
token := c.Query("token")
|
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: "参数缺失"})
|
c.JSON(http.StatusBadRequest, model.WrapperResponse{Code: 400, Msg: "参数缺失"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// find app by code
|
// find app by code
|
||||||
var app model.Application
|
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 {
|
if !has {
|
||||||
c.JSON(http.StatusOK, model.WrapperResponse{Code: 1001, Msg: "配置不存在"})
|
c.JSON(http.StatusOK, model.WrapperResponse{Code: 1001, Msg: "配置不存在"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate token if app has token configured
|
// 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 无效"})
|
c.JSON(http.StatusForbidden, model.WrapperResponse{Code: 403, Msg: "Token 无效"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -50,10 +63,10 @@ func (h *ConfigApiHandler) FetchAllConfigs(c *gin.Context) {
|
|||||||
result := make(map[string]interface{})
|
result := make(map[string]interface{})
|
||||||
|
|
||||||
// load global configs
|
// load global configs
|
||||||
if !ignoreGlobal && app.GroupId != nil {
|
if !req.IgnoreGlobal && app.GroupId != nil {
|
||||||
var globalConfigs []model.AppConfig
|
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)",
|
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 {
|
for _, cfg := range globalConfigs {
|
||||||
kvMap := h.parseService.ParseConfigToKVMap(&cfg)
|
kvMap := h.parseService.ParseConfigToKVMap(&cfg)
|
||||||
for k, v := range kvMap {
|
for k, v := range kvMap {
|
||||||
@@ -66,7 +79,7 @@ func (h *ConfigApiHandler) FetchAllConfigs(c *gin.Context) {
|
|||||||
if app.ParentId != nil {
|
if app.ParentId != nil {
|
||||||
var parentConfigs []model.AppConfig
|
var parentConfigs []model.AppConfig
|
||||||
dao.Engine.Where("env = ? AND version = ? AND enabled = 1 AND app_id = ?",
|
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 {
|
for _, cfg := range parentConfigs {
|
||||||
kvMap := h.parseService.ParseConfigToKVMap(&cfg)
|
kvMap := h.parseService.ParseConfigToKVMap(&cfg)
|
||||||
for k, v := range kvMap {
|
for k, v := range kvMap {
|
||||||
@@ -78,7 +91,7 @@ func (h *ConfigApiHandler) FetchAllConfigs(c *gin.Context) {
|
|||||||
// load app configs
|
// load app configs
|
||||||
var appConfigs []model.AppConfig
|
var appConfigs []model.AppConfig
|
||||||
dao.Engine.Where("env = ? AND version = ? AND enabled = 1 AND app_id = ?",
|
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 {
|
for _, cfg := range appConfigs {
|
||||||
kvMap := h.parseService.ParseConfigToKVMap(&cfg)
|
kvMap := h.parseService.ParseConfigToKVMap(&cfg)
|
||||||
for k, v := range kvMap {
|
for k, v := range kvMap {
|
||||||
@@ -92,9 +105,9 @@ func (h *ConfigApiHandler) FetchAllConfigs(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add encryption keys
|
// add encryption keys
|
||||||
globalCryptKey := h.cryptoService.GetCryptKey(0, env)
|
globalCryptKey := h.cryptoService.GetCryptKey(0, req.Env)
|
||||||
result["kenaito.config.global-encrypt-secret"] = globalCryptKey
|
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["kenaito.config.encrypt-secret"] = appCryptKey
|
||||||
result["latest.fetch.timestamp"] = strconv.FormatInt(time.Now().UnixMilli(), 10)
|
result["latest.fetch.timestamp"] = strconv.FormatInt(time.Now().UnixMilli(), 10)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user