[优化] 重构 API 处理逻辑,简化参数解析和响应处理

This commit is contained in:
ryan
2026-05-31 13:31:32 +08:00
parent bcd669722e
commit ec70794577
11 changed files with 183 additions and 547 deletions
+2 -10
View File
@@ -2,7 +2,6 @@ package controller
import (
"github.com/gin-gonic/gin"
"net/http"
"openflare/model"
)
@@ -16,15 +15,8 @@ import (
func GetDefaultAcmeAccount(c *gin.Context) {
account, err := model.GetDefaultAcmeAccount()
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": account,
})
respondSuccess(c, account)
}
+1 -6
View File
@@ -1,7 +1,6 @@
package controller
import (
"net/http"
"openflare/service"
"github.com/gin-gonic/gin"
@@ -18,11 +17,7 @@ import (
func CleanupDatabaseObservability(c *gin.Context) {
var input service.DatabaseCleanupInput
if err := decodeOptionalJSONBody(c.Request.Body, &input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": "参数错误",
"error": err.Error(),
})
respondBadRequest(c, "")
return
}
result, err := service.CleanupDatabaseObservability(input)
+19 -74
View File
@@ -1,11 +1,8 @@
package controller
import (
"encoding/json"
"github.com/gin-gonic/gin"
"net/http"
"openflare/model"
"strconv"
)
type DnsAccountInput struct {
@@ -24,17 +21,10 @@ type DnsAccountInput struct {
func GetDnsAccounts(c *gin.Context) {
accounts, err := model.ListDnsAccounts()
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": accounts,
})
respondSuccess(c, accounts)
}
// CreateDnsAccount godoc
@@ -48,11 +38,7 @@ func GetDnsAccounts(c *gin.Context) {
// @Router /api/dns-accounts/ [post]
func CreateDnsAccount(c *gin.Context) {
var input DnsAccountInput
if err := json.NewDecoder(c.Request.Body).Decode(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": "无效的参数",
})
if !bindJSON(c, &input) {
return
}
@@ -63,18 +49,11 @@ func CreateDnsAccount(c *gin.Context) {
}
if err := account.Insert(); 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": account,
})
respondSuccess(c, account)
}
// UpdateDnsAccount godoc
@@ -88,30 +67,19 @@ func CreateDnsAccount(c *gin.Context) {
// @Success 200 {object} map[string]interface{}
// @Router /api/dns-accounts/{id}/update [post]
func UpdateDnsAccount(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": "无效的参数",
})
id, ok := parseIDParam(c)
if !ok {
return
}
var input DnsAccountInput
if err := json.NewDecoder(c.Request.Body).Decode(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": "无效的参数",
})
if !bindJSON(c, &input) {
return
}
account, err := model.GetDnsAccountByID(uint(id))
account, err := model.GetDnsAccountByID(id)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
respondFailure(c, err.Error())
return
}
@@ -120,18 +88,11 @@ func UpdateDnsAccount(c *gin.Context) {
account.Authorization = input.Authorization
if err := account.Update(); 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": account,
})
respondSuccess(c, account)
}
// DeleteDnsAccount godoc
@@ -143,21 +104,14 @@ func UpdateDnsAccount(c *gin.Context) {
// @Success 200 {object} map[string]interface{}
// @Router /api/dns-accounts/{id}/delete [post]
func DeleteDnsAccount(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": "无效的参数",
})
id, ok := parseIDParam(c)
if !ok {
return
}
account, err := model.GetDnsAccountByID(uint(id))
account, err := model.GetDnsAccountByID(id)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
respondFailure(c, err.Error())
return
}
@@ -165,23 +119,14 @@ func DeleteDnsAccount(c *gin.Context) {
var count int64
model.DB.Model(&model.TLSCertificate{}).Where("dns_account_id = ?", id).Count(&count)
if count > 0 {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "该 DNS 账号已被证书使用,无法删除",
})
respondFailure(c, "该 DNS 账号已被证书使用,无法删除")
return
}
if err := account.Delete(); 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": "",
})
respondSuccess(c, nil)
}
+1 -2
View File
@@ -22,8 +22,7 @@ type geoIPLookupRequest struct {
// @Router /api/option/geoip/lookup [post]
func LookupGeoIP(c *gin.Context) {
var request geoIPLookupRequest
if err := decodeJSONBody(c.Request.Body, &request); err != nil {
respondBadRequest(c, "")
if !bindJSON(c, &request) {
return
}
+18 -71
View File
@@ -1,11 +1,8 @@
package controller
import (
"encoding/json"
"github.com/gin-gonic/gin"
"net/http"
"openflare/service"
"strconv"
"strings"
)
@@ -19,17 +16,10 @@ import (
func GetManagedDomains(c *gin.Context) {
domains, err := service.ListManagedDomains()
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": domains,
})
respondSuccess(c, domains)
}
// CreateManagedDomain godoc
@@ -44,26 +34,15 @@ func GetManagedDomains(c *gin.Context) {
// @Router /api/managed-domains/ [post]
func CreateManagedDomain(c *gin.Context) {
var input service.ManagedDomainInput
if err := json.NewDecoder(c.Request.Body).Decode(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": "无效的参数",
})
if !bindJSON(c, &input) {
return
}
domain, err := service.CreateManagedDomain(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": domain,
})
respondSuccess(c, domain)
}
// UpdateManagedDomain godoc
@@ -78,35 +57,20 @@ func CreateManagedDomain(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/managed-domains/{id}/update [post]
func UpdateManagedDomain(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": "无效的参数",
})
id, ok := parseIDParam(c)
if !ok {
return
}
var input service.ManagedDomainInput
if err = json.NewDecoder(c.Request.Body).Decode(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": "无效的参数",
})
if !bindJSON(c, &input) {
return
}
domain, err := service.UpdateManagedDomain(uint(id), input)
domain, err := service.UpdateManagedDomain(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": domain,
})
respondSuccess(c, domain)
}
// DeleteManagedDomain godoc
@@ -119,25 +83,15 @@ func UpdateManagedDomain(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/managed-domains/{id}/delete [post]
func DeleteManagedDomain(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": "无效的参数",
})
id, ok := parseIDParam(c)
if !ok {
return
}
if err = service.DeleteManagedDomain(uint(id)); err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
if err := service.DeleteManagedDomain(id); err != nil {
respondFailure(c, err.Error())
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
})
respondSuccess(c, nil)
}
// MatchManagedDomainCertificate godoc
@@ -152,15 +106,8 @@ func MatchManagedDomainCertificate(c *gin.Context) {
domain := strings.TrimSpace(c.Query("domain"))
result, err := service.MatchManagedDomainCertificate(domain)
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)
}
+28 -39
View File
@@ -2,7 +2,6 @@ package controller
import (
"openflare/service"
"strconv"
"github.com/gin-gonic/gin"
)
@@ -29,8 +28,7 @@ type nodeObservabilityQuery struct {
// @Router /api/nodes/ [post]
func CreateNode(c *gin.Context) {
var input service.NodeInput
if err := decodeJSONBody(c.Request.Body, &input); err != nil {
respondBadRequest(c, "")
if !bindJSON(c, &input) {
return
}
@@ -86,19 +84,17 @@ func RotateNodeBootstrapToken(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/nodes/{id}/update [post]
func UpdateNode(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil || id == 0 {
respondBadRequest(c, "")
id, ok := parseIDParam(c)
if !ok {
return
}
var input service.NodeInput
if err = decodeJSONBody(c.Request.Body, &input); err != nil {
respondBadRequest(c, "")
if !bindJSON(c, &input) {
return
}
node, err := service.UpdateNode(uint(id), input)
node, err := service.UpdateNode(id, input)
if err != nil {
respondFailure(c, err.Error())
return
@@ -116,13 +112,12 @@ func UpdateNode(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/nodes/{id}/delete [post]
func DeleteNode(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil || id == 0 {
respondBadRequest(c, "")
id, ok := parseIDParam(c)
if !ok {
return
}
if err = service.DeleteNode(uint(id)); err != nil {
if err := service.DeleteNode(id); err != nil {
respondFailure(c, err.Error())
return
}
@@ -139,21 +134,20 @@ func DeleteNode(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/nodes/{id}/agent-update [post]
func RequestNodeAgentUpdate(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil || id == 0 {
respondBadRequest(c, "")
id, ok := parseIDParam(c)
if !ok {
return
}
var request nodeAgentUpdateRequest
if c.Request.ContentLength > 0 {
if err = decodeOptionalJSONBody(c.Request.Body, &request); err != nil {
if err := decodeOptionalJSONBody(c.Request.Body, &request); err != nil {
respondBadRequest(c, "")
return
}
}
node, err := service.RequestNodeAgentUpdate(uint(id), service.NodeAgentUpdateInput{
node, err := service.RequestNodeAgentUpdate(id, service.NodeAgentUpdateInput{
Channel: request.Channel,
TagName: request.TagName,
})
@@ -174,13 +168,12 @@ func RequestNodeAgentUpdate(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/nodes/{id}/openresty-restart [post]
func RequestNodeOpenrestyRestart(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil || id == 0 {
respondBadRequest(c, "")
id, ok := parseIDParam(c)
if !ok {
return
}
node, err := service.RequestNodeOpenrestyRestart(uint(id))
node, err := service.RequestNodeOpenrestyRestart(id)
if err != nil {
respondFailure(c, err.Error())
return
@@ -198,13 +191,12 @@ func RequestNodeOpenrestyRestart(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/nodes/{id}/force-sync [post]
func RequestNodeForceSync(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil || id == 0 {
respondBadRequest(c, "")
id, ok := parseIDParam(c)
if !ok {
return
}
node, err := service.RequestNodeForceSync(uint(id))
node, err := service.RequestNodeForceSync(id)
if err != nil {
respondFailure(c, err.Error())
return
@@ -223,13 +215,12 @@ func RequestNodeForceSync(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/nodes/{id}/agent-release [get]
func GetNodeAgentRelease(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil || id == 0 {
respondBadRequest(c, "")
id, ok := parseIDParam(c)
if !ok {
return
}
release, err := service.GetNodeAgentRelease(c.Request.Context(), uint(id), c.Query("channel"))
release, err := service.GetNodeAgentRelease(c.Request.Context(), id, c.Query("channel"))
if err != nil {
respondFailure(c, err.Error())
return
@@ -249,19 +240,18 @@ func GetNodeAgentRelease(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/nodes/{id}/observability [get]
func GetNodeObservability(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil || id == 0 {
respondBadRequest(c, "")
id, ok := parseIDParam(c)
if !ok {
return
}
var query nodeObservabilityQuery
if err = c.ShouldBindQuery(&query); err != nil {
if err := c.ShouldBindQuery(&query); err != nil {
respondBadRequest(c, "")
return
}
view, err := service.GetNodeObservability(uint(id), service.NodeObservabilityQuery{
view, err := service.GetNodeObservability(id, service.NodeObservabilityQuery{
Hours: query.Hours,
Limit: query.Limit,
})
@@ -282,13 +272,12 @@ func GetNodeObservability(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/nodes/{id}/observability/cleanup [post]
func CleanupNodeHealthEvents(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil || id == 0 {
respondBadRequest(c, "")
id, ok := parseIDParam(c)
if !ok {
return
}
result, err := service.CleanupNodeHealthEvents(uint(id))
result, err := service.CleanupNodeHealthEvents(id)
if err != nil {
respondFailure(c, err.Error())
return
+22 -80
View File
@@ -1,128 +1,70 @@
package controller
import (
"encoding/json"
"net/http"
"openflare/service"
"strconv"
"github.com/gin-gonic/gin"
"openflare/service"
)
func GetOrigins(c *gin.Context) {
origins, err := service.ListOrigins()
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": origins,
})
respondSuccess(c, origins)
}
func GetOrigin(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": "无效的参数",
})
id, ok := parseIDParam(c)
if !ok {
return
}
origin, err := service.GetOriginDetail(uint(id))
origin, err := service.GetOriginDetail(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": origin,
})
respondSuccess(c, origin)
}
func CreateOrigin(c *gin.Context) {
var input service.OriginInput
if err := json.NewDecoder(c.Request.Body).Decode(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": "无效的参数",
})
if !bindJSON(c, &input) {
return
}
origin, err := service.CreateOrigin(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": origin,
})
respondSuccess(c, origin)
}
func UpdateOrigin(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": "无效的参数",
})
id, ok := parseIDParam(c)
if !ok {
return
}
var input service.OriginInput
if err = json.NewDecoder(c.Request.Body).Decode(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": "无效的参数",
})
if !bindJSON(c, &input) {
return
}
origin, err := service.UpdateOrigin(uint(id), input)
origin, err := service.UpdateOrigin(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": origin,
})
respondSuccess(c, origin)
}
func DeleteOrigin(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": "无效的参数",
})
id, ok := parseIDParam(c)
if !ok {
return
}
if err = service.DeleteOrigin(uint(id)); err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
if err := service.DeleteOrigin(id); err != nil {
respondFailure(c, err.Error())
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
})
respondSuccess(c, nil)
}
+22 -80
View File
@@ -1,12 +1,8 @@
package controller
import (
"encoding/json"
"net/http"
"openflare/service"
"strconv"
"github.com/gin-gonic/gin"
"openflare/service"
)
// GetProxyRoutes godoc
@@ -19,17 +15,10 @@ import (
func GetProxyRoutes(c *gin.Context) {
routes, err := service.ListProxyRoutes()
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": routes,
})
respondSuccess(c, routes)
}
// GetProxyRoute godoc
@@ -42,27 +31,16 @@ func GetProxyRoutes(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/proxy-routes/{id} [get]
func GetProxyRoute(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": "invalid id",
})
id, ok := parseIDParam(c)
if !ok {
return
}
route, err := service.GetProxyRoute(uint(id))
route, err := service.GetProxyRoute(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": route,
})
respondSuccess(c, route)
}
// CreateProxyRoute godoc
@@ -77,26 +55,15 @@ func GetProxyRoute(c *gin.Context) {
// @Router /api/proxy-routes/ [post]
func CreateProxyRoute(c *gin.Context) {
var input service.ProxyRouteInput
if err := json.NewDecoder(c.Request.Body).Decode(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": "invalid payload",
})
if !bindJSON(c, &input) {
return
}
route, err := service.CreateProxyRoute(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": route,
})
respondSuccess(c, route)
}
// UpdateProxyRoute godoc
@@ -111,35 +78,20 @@ func CreateProxyRoute(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/proxy-routes/{id}/update [post]
func UpdateProxyRoute(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": "invalid id",
})
id, ok := parseIDParam(c)
if !ok {
return
}
var input service.ProxyRouteInput
if err = json.NewDecoder(c.Request.Body).Decode(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": "invalid payload",
})
if !bindJSON(c, &input) {
return
}
route, err := service.UpdateProxyRoute(uint(id), input)
route, err := service.UpdateProxyRoute(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": route,
})
respondSuccess(c, route)
}
// DeleteProxyRoute godoc
@@ -152,23 +104,13 @@ func UpdateProxyRoute(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/proxy-routes/{id}/delete [post]
func DeleteProxyRoute(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": "invalid id",
})
id, ok := parseIDParam(c)
if !ok {
return
}
if err = service.DeleteProxyRoute(uint(id)); err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
if err := service.DeleteProxyRoute(id); err != nil {
respondFailure(c, err.Error())
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
})
respondSuccess(c, nil)
}
+19 -1
View File
@@ -5,11 +5,12 @@ import (
"errors"
"io"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
)
const invalidParamsMessage = "鏃犳晥鐨勫弬鏁?"
const invalidParamsMessage = "参数错误"
func respondSuccess(c *gin.Context, data any) {
c.JSON(http.StatusOK, gin.H{
@@ -72,3 +73,20 @@ func decodeOptionalJSONBody(body io.Reader, target any) error {
}
return nil
}
func parseIDParam(c *gin.Context) (uint, bool) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil || id == 0 {
respondBadRequest(c, "")
return 0, false
}
return uint(id), true
}
func bindJSON(c *gin.Context, target any) bool {
if err := decodeJSONBody(c.Request.Body, target); err != nil {
respondBadRequest(c, "")
return false
}
return true
}
+50 -183
View File
@@ -1,11 +1,8 @@
package controller
import (
"encoding/json"
"github.com/gin-gonic/gin"
"net/http"
"openflare/service"
"strconv"
)
// GetTLSCertificates godoc
@@ -18,17 +15,10 @@ import (
func GetTLSCertificates(c *gin.Context) {
certificates, err := service.ListTLSCertificates()
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": certificates,
})
respondSuccess(c, certificates)
}
// GetTLSCertificate godoc
@@ -41,28 +31,17 @@ func GetTLSCertificates(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/tls-certificates/{id} [get]
func GetTLSCertificate(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": "invalid request",
})
id, ok := parseIDParam(c)
if !ok {
return
}
certificate, err := service.GetTLSCertificate(uint(id))
certificate, err := service.GetTLSCertificate(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": certificate,
})
respondSuccess(c, certificate)
}
// GetTLSCertificateContent godoc
@@ -75,28 +54,17 @@ func GetTLSCertificate(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/tls-certificates/{id}/content [get]
func GetTLSCertificateContent(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": "invalid request",
})
id, ok := parseIDParam(c)
if !ok {
return
}
content, err := service.GetTLSCertificateContent(uint(id))
content, err := service.GetTLSCertificateContent(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": content,
})
respondSuccess(c, content)
}
// CreateTLSCertificate godoc
@@ -111,26 +79,15 @@ func GetTLSCertificateContent(c *gin.Context) {
// @Router /api/tls-certificates/ [post]
func CreateTLSCertificate(c *gin.Context) {
var input service.TLSCertificateInput
if err := json.NewDecoder(c.Request.Body).Decode(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": "无效的参数",
})
if !bindJSON(c, &input) {
return
}
certificate, err := service.CreateTLSCertificate(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": certificate,
})
respondSuccess(c, certificate)
}
// UpdateTLSCertificate godoc
@@ -145,37 +102,22 @@ func CreateTLSCertificate(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/tls-certificates/{id}/update [post]
func UpdateTLSCertificate(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": "invalid request",
})
id, ok := parseIDParam(c)
if !ok {
return
}
var input service.TLSCertificateInput
if err = json.NewDecoder(c.Request.Body).Decode(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": "invalid request",
})
if !bindJSON(c, &input) {
return
}
certificate, err := service.UpdateTLSCertificate(uint(id), input)
certificate, err := service.UpdateTLSCertificate(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": certificate,
})
respondSuccess(c, certificate)
}
// ImportTLSCertificateFile godoc
@@ -196,33 +138,20 @@ func ImportTLSCertificateFile(c *gin.Context) {
remark := c.PostForm("remark")
certFile, err := c.FormFile("cert_file")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": "缺少证书文件",
})
respondBadRequest(c, "缺少证书文件")
return
}
keyFile, err := c.FormFile("key_file")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": "缺少私钥文件",
})
respondBadRequest(c, "缺少私钥文件")
return
}
certificate, err := service.CreateTLSCertificateFromFiles(name, certFile, keyFile, remark)
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": certificate,
})
respondSuccess(c, certificate)
}
// DeleteTLSCertificate godoc
@@ -235,25 +164,15 @@ func ImportTLSCertificateFile(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/tls-certificates/{id}/delete [post]
func DeleteTLSCertificate(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": "无效的参数",
})
id, ok := parseIDParam(c)
if !ok {
return
}
if err = service.DeleteTLSCertificate(uint(id)); err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
if err := service.DeleteTLSCertificate(id); err != nil {
respondFailure(c, err.Error())
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
})
respondSuccess(c, nil)
}
// ApplyTLSCertificate godoc
@@ -268,26 +187,15 @@ func DeleteTLSCertificate(c *gin.Context) {
// @Router /api/tls-certificates/apply [post]
func ApplyTLSCertificate(c *gin.Context) {
var input service.TLSApplyInput
if err := json.NewDecoder(c.Request.Body).Decode(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": "无效的参数",
})
if !bindJSON(c, &input) {
return
}
certificate, err := service.ApplyTLSCertificate(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": certificate,
})
respondSuccess(c, certificate)
}
// UpdateAcmeCertificate godoc
@@ -302,36 +210,21 @@ func ApplyTLSCertificate(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/tls-certificates/{id}/update-acme [post]
func UpdateAcmeCertificate(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": "invalid request",
})
id, ok := parseIDParam(c)
if !ok {
return
}
var input service.TLSApplyInput
if err := json.NewDecoder(c.Request.Body).Decode(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": "无效的参数",
})
if !bindJSON(c, &input) {
return
}
certificate, err := service.UpdateAcmeCertificate(uint(id), input)
certificate, err := service.UpdateAcmeCertificate(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": certificate,
})
respondSuccess(c, certificate)
}
// ConvertTLSCertificateToAcme godoc
@@ -346,36 +239,21 @@ func UpdateAcmeCertificate(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/tls-certificates/{id}/convert-acme [post]
func ConvertTLSCertificateToAcme(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": "invalid request",
})
id, ok := parseIDParam(c)
if !ok {
return
}
var input service.TLSApplyInput
if err := json.NewDecoder(c.Request.Body).Decode(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"message": "无效的参数",
})
if !bindJSON(c, &input) {
return
}
certificate, err := service.ConvertTLSCertificateToAcme(uint(id), input)
certificate, err := service.ConvertTLSCertificateToAcme(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": certificate,
})
respondSuccess(c, certificate)
}
// RenewTLSCertificate godoc
@@ -388,25 +266,14 @@ func ConvertTLSCertificateToAcme(c *gin.Context) {
// @Failure 400 {object} map[string]interface{}
// @Router /api/tls-certificates/{id}/renew [post]
func RenewTLSCertificate(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": "无效的参数",
})
id, ok := parseIDParam(c)
if !ok {
return
}
certificate, err := service.RenewTLSCertificate(uint(id))
certificate, err := service.RenewTLSCertificate(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": certificate,
})
respondSuccess(c, certificate)
}
+1 -1
View File
@@ -452,7 +452,7 @@ func TestTLSCertificateConvertAcmeAPI(t *testing.T) {
}
invalidResp := performJSONRequestNoFatal(t, engine, token, http.MethodPost, "/api/tls-certificates/not-a-number/convert-acme", map[string]any{})
if invalidResp.Success || !strings.Contains(invalidResp.Message, "invalid request") {
if invalidResp.Success || !strings.Contains(invalidResp.Message, "参数错误") {
t.Fatalf("expected invalid id to fail, got %+v", invalidResp)
}