From 8aef32c0ccfac63e96bbe6d1fdafdbad51db1d4d Mon Sep 17 00:00:00 2001 From: ryan Date: Fri, 13 Mar 2026 16:08:59 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=87=8D=E6=9E=84=E5=93=8D=E5=BA=94?= =?UTF-8?q?=E5=A4=84=E7=90=86=EF=BC=8C=E6=B7=BB=E5=8A=A0=E9=80=9A=E7=94=A8?= =?UTF-8?q?=E5=93=8D=E5=BA=94=E5=87=BD=E6=95=B0=E4=BB=A5=E7=AE=80=E5=8C=96?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- atsf_server/controller/agent.go | 101 +++++--------------- atsf_server/controller/node.go | 145 +++++++---------------------- atsf_server/controller/response.go | 74 +++++++++++++++ 3 files changed, 134 insertions(+), 186 deletions(-) create mode 100644 atsf_server/controller/response.go diff --git a/atsf_server/controller/agent.go b/atsf_server/controller/agent.go index 95a24dcf..049d171a 100644 --- a/atsf_server/controller/agent.go +++ b/atsf_server/controller/agent.go @@ -3,8 +3,6 @@ package controller import ( "atsflare/model" "atsflare/service" - "encoding/json" - "net/http" "github.com/gin-gonic/gin" ) @@ -21,13 +19,11 @@ import ( // @Router /api/agent/nodes/register [post] func AgentRegister(c *gin.Context) { var payload service.AgentNodePayload - if err := json.NewDecoder(c.Request.Body).Decode(&payload); err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "success": false, - "message": "无效的参数", - }) + if err := decodeJSONBody(c.Request.Body, &payload); err != nil { + respondBadRequest(c, "") return } + var ( result *service.AgentRegistrationResponse err error @@ -38,17 +34,10 @@ func AgentRegister(c *gin.Context) { result, err = service.RegisterNodeWithDiscovery(payload) } if err != nil { - c.JSON(http.StatusOK, gin.H{ - "success": false, - "message": err.Error(), - }) + respondFailure(c, err.Error()) return } - c.JSON(http.StatusOK, gin.H{ - "success": true, - "message": "", - "data": result, - }) + respondSuccess(c, result) } // AgentHeartbeat godoc @@ -63,33 +52,23 @@ func AgentRegister(c *gin.Context) { // @Router /api/agent/nodes/heartbeat [post] func AgentHeartbeat(c *gin.Context) { var payload service.AgentNodePayload - if err := json.NewDecoder(c.Request.Body).Decode(&payload); err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "success": false, - "message": "无效的参数", - }) + if err := decodeJSONBody(c.Request.Body, &payload); err != nil { + respondBadRequest(c, "") return } + authNode, ok := c.Get("agent_node") if !ok { - c.JSON(http.StatusUnauthorized, gin.H{ - "success": false, - "message": "无权进行此操作,Agent Token 无效", - }) + respondUnauthorized(c, "鏃犳潈杩涜姝ゆ搷浣滐紝Agent Token 鏃犳晥") return } + node, err := service.HeartbeatNode(authNode.(*model.Node), payload) if err != nil { - c.JSON(http.StatusOK, gin.H{ - "success": false, - "message": err.Error(), - }) + respondFailure(c, err.Error()) return } - c.JSON(http.StatusOK, gin.H{ - "success": true, - "message": "", - "data": node.Node, + respondSuccessWithExtras(c, node.Node, gin.H{ "agent_settings": node.AgentSettings, "active_config": node.ActiveConfig, }) @@ -105,17 +84,10 @@ func AgentHeartbeat(c *gin.Context) { func AgentGetActiveConfig(c *gin.Context) { config, err := service.GetActiveConfigForAgent() if err != nil { - c.JSON(http.StatusOK, gin.H{ - "success": false, - "message": "当前没有激活版本", - }) + respondFailure(c, "褰撳墠娌℃湁婵€娲荤増鏈?") return } - c.JSON(http.StatusOK, gin.H{ - "success": true, - "message": "", - "data": config, - }) + respondSuccess(c, config) } // AgentReportApplyLog godoc @@ -130,30 +102,21 @@ func AgentGetActiveConfig(c *gin.Context) { // @Router /api/agent/apply-logs [post] func AgentReportApplyLog(c *gin.Context) { var payload service.ApplyLogPayload - if err := json.NewDecoder(c.Request.Body).Decode(&payload); err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "success": false, - "message": "无效的参数", - }) + if err := decodeJSONBody(c.Request.Body, &payload); err != nil { + respondBadRequest(c, "") return } - authNode, ok := c.Get("agent_node") - if ok { + + if authNode, ok := c.Get("agent_node"); ok { payload.NodeID = authNode.(*model.Node).NodeID } + log, err := service.ReportApplyLog(payload) if err != nil { - c.JSON(http.StatusOK, gin.H{ - "success": false, - "message": err.Error(), - }) + respondFailure(c, err.Error()) return } - c.JSON(http.StatusOK, gin.H{ - "success": true, - "message": "", - "data": log, - }) + respondSuccess(c, log) } // GetNodes godoc @@ -166,17 +129,10 @@ func AgentReportApplyLog(c *gin.Context) { func GetNodes(c *gin.Context) { nodes, err := service.ListNodeViews() if err != nil { - c.JSON(http.StatusOK, gin.H{ - "success": false, - "message": err.Error(), - }) + respondFailure(c, err.Error()) return } - c.JSON(http.StatusOK, gin.H{ - "success": true, - "message": "", - "data": nodes, - }) + respondSuccess(c, nodes) } // GetApplyLogs godoc @@ -190,15 +146,8 @@ func GetNodes(c *gin.Context) { func GetApplyLogs(c *gin.Context) { logs, err := service.ListApplyLogs(c.Query("node_id")) if err != nil { - c.JSON(http.StatusOK, gin.H{ - "success": false, - "message": err.Error(), - }) + respondFailure(c, err.Error()) return } - c.JSON(http.StatusOK, gin.H{ - "success": true, - "message": "", - "data": logs, - }) + respondSuccess(c, logs) } diff --git a/atsf_server/controller/node.go b/atsf_server/controller/node.go index 395d2c16..7182e1d2 100644 --- a/atsf_server/controller/node.go +++ b/atsf_server/controller/node.go @@ -2,10 +2,6 @@ package controller import ( "atsflare/service" - "encoding/json" - "errors" - "io" - "net/http" "strconv" "github.com/gin-gonic/gin" @@ -28,26 +24,17 @@ type nodeAgentUpdateRequest struct { // @Router /api/nodes/ [post] func CreateNode(c *gin.Context) { var input service.NodeInput - if err := json.NewDecoder(c.Request.Body).Decode(&input); err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "success": false, - "message": "无效的参数", - }) + if err := decodeJSONBody(c.Request.Body, &input); err != nil { + respondBadRequest(c, "") return } + node, err := service.CreateNode(input) if err != nil { - c.JSON(http.StatusOK, gin.H{ - "success": false, - "message": err.Error(), - }) + respondFailure(c, err.Error()) return } - c.JSON(http.StatusOK, gin.H{ - "success": true, - "message": "", - "data": node, - }) + respondSuccess(c, node) } // GetNodeBootstrapToken godoc @@ -60,17 +47,10 @@ func CreateNode(c *gin.Context) { func GetNodeBootstrapToken(c *gin.Context) { bootstrap, err := service.GetNodeBootstrapView() if err != nil { - c.JSON(http.StatusOK, gin.H{ - "success": false, - "message": err.Error(), - }) + respondFailure(c, err.Error()) return } - c.JSON(http.StatusOK, gin.H{ - "success": true, - "message": "", - "data": bootstrap, - }) + respondSuccess(c, bootstrap) } // RotateNodeBootstrapToken godoc @@ -83,17 +63,10 @@ func GetNodeBootstrapToken(c *gin.Context) { func RotateNodeBootstrapToken(c *gin.Context) { bootstrap, err := service.RotateGlobalDiscoveryToken() if err != nil { - c.JSON(http.StatusOK, gin.H{ - "success": false, - "message": err.Error(), - }) + respondFailure(c, err.Error()) return } - c.JSON(http.StatusOK, gin.H{ - "success": true, - "message": "", - "data": bootstrap, - }) + respondSuccess(c, bootstrap) } // UpdateNode godoc @@ -110,33 +83,22 @@ func RotateNodeBootstrapToken(c *gin.Context) { func UpdateNode(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil || id == 0 { - c.JSON(http.StatusBadRequest, gin.H{ - "success": false, - "message": "无效的参数", - }) + respondBadRequest(c, "") return } + var input service.NodeInput - if err = json.NewDecoder(c.Request.Body).Decode(&input); err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "success": false, - "message": "无效的参数", - }) + if err = decodeJSONBody(c.Request.Body, &input); err != nil { + respondBadRequest(c, "") return } + node, err := service.UpdateNode(uint(id), input) if err != nil { - c.JSON(http.StatusOK, gin.H{ - "success": false, - "message": err.Error(), - }) + respondFailure(c, err.Error()) return } - c.JSON(http.StatusOK, gin.H{ - "success": true, - "message": "", - "data": node, - }) + respondSuccess(c, node) } // DeleteNode godoc @@ -151,23 +113,15 @@ func UpdateNode(c *gin.Context) { func DeleteNode(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil || id == 0 { - c.JSON(http.StatusBadRequest, gin.H{ - "success": false, - "message": "无效的参数", - }) + respondBadRequest(c, "") return } + if err = service.DeleteNode(uint(id)); err != nil { - c.JSON(http.StatusOK, gin.H{ - "success": false, - "message": err.Error(), - }) + respondFailure(c, err.Error()) return } - c.JSON(http.StatusOK, gin.H{ - "success": true, - "message": "", - }) + respondSuccessMessage(c, "") } // RequestNodeAgentUpdate godoc @@ -182,38 +136,27 @@ func DeleteNode(c *gin.Context) { func RequestNodeAgentUpdate(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil || id == 0 { - c.JSON(http.StatusBadRequest, gin.H{ - "success": false, - "message": "无效的参数", - }) + respondBadRequest(c, "") return } + var request nodeAgentUpdateRequest if c.Request.ContentLength > 0 { - if err = json.NewDecoder(c.Request.Body).Decode(&request); err != nil && !errors.Is(err, io.EOF) { - c.JSON(http.StatusBadRequest, gin.H{ - "success": false, - "message": "无效的参数", - }) + if err = decodeOptionalJSONBody(c.Request.Body, &request); err != nil { + respondBadRequest(c, "") return } } + node, err := service.RequestNodeAgentUpdate(uint(id), service.NodeAgentUpdateInput{ Channel: request.Channel, TagName: request.TagName, }) if err != nil { - c.JSON(http.StatusOK, gin.H{ - "success": false, - "message": err.Error(), - }) + respondFailure(c, err.Error()) return } - c.JSON(http.StatusOK, gin.H{ - "success": true, - "message": "", - "data": node, - }) + respondSuccess(c, node) } // RequestNodeOpenrestyRestart godoc @@ -228,25 +171,16 @@ func RequestNodeAgentUpdate(c *gin.Context) { func RequestNodeOpenrestyRestart(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil || id == 0 { - c.JSON(http.StatusBadRequest, gin.H{ - "success": false, - "message": "无效的参数", - }) + respondBadRequest(c, "") return } + node, err := service.RequestNodeOpenrestyRestart(uint(id)) if err != nil { - c.JSON(http.StatusOK, gin.H{ - "success": false, - "message": err.Error(), - }) + respondFailure(c, err.Error()) return } - c.JSON(http.StatusOK, gin.H{ - "success": true, - "message": "", - "data": node, - }) + respondSuccess(c, node) } // GetNodeAgentRelease godoc @@ -262,23 +196,14 @@ func RequestNodeOpenrestyRestart(c *gin.Context) { func GetNodeAgentRelease(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil || id == 0 { - c.JSON(http.StatusBadRequest, gin.H{ - "success": false, - "message": "无效的参数", - }) + respondBadRequest(c, "") return } + release, err := service.GetNodeAgentRelease(c.Request.Context(), uint(id), c.Query("channel")) if err != nil { - c.JSON(http.StatusOK, gin.H{ - "success": false, - "message": err.Error(), - }) + respondFailure(c, err.Error()) return } - c.JSON(http.StatusOK, gin.H{ - "success": true, - "message": "", - "data": release, - }) + respondSuccess(c, release) } diff --git a/atsf_server/controller/response.go b/atsf_server/controller/response.go new file mode 100644 index 00000000..713dc548 --- /dev/null +++ b/atsf_server/controller/response.go @@ -0,0 +1,74 @@ +package controller + +import ( + "encoding/json" + "errors" + "io" + "net/http" + + "github.com/gin-gonic/gin" +) + +const invalidParamsMessage = "鏃犳晥鐨勫弬鏁?" + +func respondSuccess(c *gin.Context, data any) { + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": "", + "data": data, + }) +} + +func respondSuccessWithExtras(c *gin.Context, data any, extras gin.H) { + payload := gin.H{ + "success": true, + "message": "", + "data": data, + } + for key, value := range extras { + payload[key] = value + } + c.JSON(http.StatusOK, payload) +} + +func respondSuccessMessage(c *gin.Context, message string) { + c.JSON(http.StatusOK, gin.H{ + "success": true, + "message": message, + }) +} + +func respondFailure(c *gin.Context, message string) { + c.JSON(http.StatusOK, gin.H{ + "success": false, + "message": message, + }) +} + +func respondBadRequest(c *gin.Context, message string) { + if message == "" { + message = invalidParamsMessage + } + c.JSON(http.StatusBadRequest, gin.H{ + "success": false, + "message": message, + }) +} + +func respondUnauthorized(c *gin.Context, message string) { + c.JSON(http.StatusUnauthorized, gin.H{ + "success": false, + "message": message, + }) +} + +func decodeJSONBody(body io.Reader, target any) error { + return json.NewDecoder(body).Decode(target) +} + +func decodeOptionalJSONBody(body io.Reader, target any) error { + if err := json.NewDecoder(body).Decode(target); err != nil && !errors.Is(err, io.EOF) { + return err + } + return nil +}