refactor(server): use Wavelet response abort helpers

Call response.AbortNotFoundIfMissing and AbortBadRequestOnError from handlers and drop the OpenFlare-local copies.
This commit is contained in:
ryan
2026-08-30 17:46:45 +08:00
parent a7c3b6a670
commit b72b1cfc16
15 changed files with 39 additions and 74 deletions
@@ -6,7 +6,6 @@ package dashboard
import (
"net/http"
"Wavelet/OpenFlare/plugins/server/kernel/apiutil"
"Wavelet/pkg/response"
"github.com/gin-gonic/gin"
@@ -26,7 +25,7 @@ import (
// @Router /api/v1/d/dashboard/overview [get]
func GetOverviewHandler(c *gin.Context) {
overview, err := GetOverview(c.Request.Context())
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(overview))
@@ -44,7 +44,7 @@ func RegisterHandler(c *gin.Context) {
} else {
result, err = RegisterWithDiscovery(c.Request.Context(), payload)
}
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(result))
@@ -76,7 +76,7 @@ func HeartbeatHandler(c *gin.Context) {
}
heartbeat, err := HeartbeatNode(c.Request.Context(), authNode, payload)
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(heartbeat))
@@ -98,7 +98,7 @@ func GetActiveConfigHandler(c *gin.Context) {
return
}
config, err := GetActiveConfig(c.Request.Context())
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(config))
@@ -122,7 +122,7 @@ func SyncWAFIPGroupsHandler(c *gin.Context) {
return
}
result, err := SyncWAFIPGroups(c.Request.Context(), input)
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(result))
@@ -149,7 +149,7 @@ func ReportApplyLogHandler(c *gin.Context) {
payload.NodeID = authNode.NodeID
}
log, err := ReportApplyLog(c.Request.Context(), payload)
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(log))
@@ -172,7 +172,7 @@ func GetPagesDeploymentHashHandler(c *gin.Context) {
return
}
hash, err := pages.GetDeploymentPackageHash(c.Request.Context(), deploymentID)
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(protocol.PagesDeploymentHashResponse{
@@ -198,7 +198,7 @@ func DownloadPagesPackageHandler(c *gin.Context) {
return
}
packageObj, err := pages.OpenDeploymentPackage(c.Request.Context(), deploymentID)
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
defer func() { _ = packageObj.Body.Close() }()
@@ -226,7 +226,7 @@ func GetPagesProjectLatestHashHandler(c *gin.Context) {
return
}
metadata, err := pages.GetProjectLatestPackageMetadata(c.Request.Context(), projectID)
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(protocol.PagesProjectLatestHashResponse{
@@ -256,7 +256,7 @@ func DownloadPagesProjectLatestPackageHandler(c *gin.Context) {
return
}
packageObj, err := pages.OpenProjectLatestPackage(c.Request.Context(), projectID)
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
defer func() { _ = packageObj.Body.Close() }()
@@ -45,7 +45,7 @@ func PostHeartbeat(c *gin.Context) {
}
result, err := Heartbeat(c.Request.Context(), node, payload)
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(result))
@@ -75,7 +75,7 @@ func GetActiveConfig(c *gin.Context) {
}
config, err := GetTunnelConfig(c.Request.Context(), node)
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(config))
@@ -106,7 +106,7 @@ func PostApplyLog(c *gin.Context) {
}
log, err := ReportApplyLog(c.Request.Context(), payload)
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(log))
@@ -19,7 +19,7 @@ func handleLogicError(c *gin.Context, err error) bool {
if err == nil {
return false
}
return apiutil.AbortNotFoundIfMissing(c, err, errNodeNotFound)
return response.AbortNotFoundIfMissing(c, err, errNodeNotFound)
}
// ListNodesHandler lists all nodes.
@@ -46,7 +46,7 @@ func PostHeartbeat(c *gin.Context) {
}
result, err := Heartbeat(c.Request.Context(), node, payload)
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(result))
@@ -39,7 +39,7 @@ func GetAccessLogOverviewHandler(c *gin.Context) {
Hours: readQueryInt(c, "hours"),
BucketMinutes: readQueryInt(c, "bucket_minutes"),
})
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(result))
@@ -70,11 +70,11 @@ func GetAccessLogOverviewHandler(c *gin.Context) {
// @Router /api/v1/d/access-logs [get]
func GetAccessLogsHandler(c *gin.Context) {
query, err := readAccessLogQuery(c)
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
logs, err := ListAccessLogs(c.Request.Context(), query)
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(logs))
@@ -103,12 +103,12 @@ func GetAccessLogsHandler(c *gin.Context) {
// @Router /api/v1/d/access-logs/folds [get]
func GetFoldedAccessLogsHandler(c *gin.Context) {
query, err := readAccessLogQuery(c)
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
query.FoldMinutes = readQueryInt(c, "fold_minutes")
logs, err := ListFoldedAccessLogs(c.Request.Context(), query)
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(logs))
@@ -149,7 +149,7 @@ func GetFoldedAccessLogIPsHandler(c *gin.Context) {
SortBy: c.Query("sort_by"),
SortOrder: c.Query("sort_order"),
})
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(result))
@@ -190,7 +190,7 @@ func GetAccessLogIPSummariesHandler(c *gin.Context) {
SortBy: c.Query("sort_by"),
SortOrder: c.Query("sort_order"),
})
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(result))
@@ -221,7 +221,7 @@ func GetAccessLogIPTrendHandler(c *gin.Context) {
Hours: readQueryInt(c, "hours"),
BucketMinutes: readQueryInt(c, "bucket_minutes"),
})
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(result))
@@ -250,7 +250,7 @@ func GetAccessLogIPAnalysisHandler(c *gin.Context) {
Host: c.Query("host"),
Hours: readQueryInt(c, "hours"),
})
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(result))
@@ -276,7 +276,7 @@ func CleanupAccessLogsHandler(c *gin.Context) {
return
}
result, err := CleanupAccessLogs(c.Request.Context(), input)
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(result))
@@ -41,7 +41,7 @@ func GetStatusHandler(c *gin.Context) {
// @Router /api/v1/d/option [get]
func ListOptionsHandler(c *gin.Context) {
options, err := listOptions(c.Request.Context())
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(options))
@@ -66,7 +66,7 @@ func UpdateOptionHandler(c *gin.Context) {
if !apiutil.BindJSON(c, &option) {
return
}
if apiutil.AbortBadRequestOnError(c, updateOption(c.Request.Context(), option)) {
if response.AbortBadRequestOnError(c, updateOption(c.Request.Context(), option)) {
return
}
c.JSON(http.StatusOK, response.OKNil())
@@ -91,7 +91,7 @@ func UpdateOptionsBatchHandler(c *gin.Context) {
if !apiutil.BindJSON(c, &payload) {
return
}
if apiutil.AbortBadRequestOnError(c, updateOptionsBatch(c.Request.Context(), payload)) {
if response.AbortBadRequestOnError(c, updateOptionsBatch(c.Request.Context(), payload)) {
return
}
c.JSON(http.StatusOK, response.OKNil())
@@ -117,7 +117,7 @@ func LookupGeoIPHandler(c *gin.Context) {
return
}
view, err := lookupGeoIP(c.Request.Context(), request.Provider, request.IP)
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(view))
@@ -137,7 +137,7 @@ func LookupGeoIPHandler(c *gin.Context) {
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/uptimekuma/sync [post]
func SyncUptimeKumaHandler(c *gin.Context) {
if apiutil.AbortBadRequestOnError(c, syncUptimeKuma(c.Request.Context())) {
if response.AbortBadRequestOnError(c, syncUptimeKuma(c.Request.Context())) {
return
}
c.JSON(http.StatusOK, response.OK("同步成功"))
@@ -24,7 +24,7 @@ func handleLogicError(c *gin.Context, err error) bool {
if err == nil {
return false
}
return apiutil.AbortNotFoundIfMissing(c, err, errPagesProjectNotFound)
return response.AbortNotFoundIfMissing(c, err, errPagesProjectNotFound)
}
func handleSourceLogicError(c *gin.Context, err error) bool {
@@ -35,7 +35,7 @@ func GetApplyLogs(c *gin.Context) {
PageNo: readIntQuery(c, "pageNo", "page_no"),
PageSize: readIntQuery(c, "pageSize", "page_size"),
})
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(result))
@@ -61,7 +61,7 @@ func CleanupApplyLogs(c *gin.Context) {
}
result, err := Cleanup(c.Request.Context(), input)
if apiutil.AbortBadRequestOnError(c, err) {
if response.AbortBadRequestOnError(c, err) {
return
}
c.JSON(http.StatusOK, response.OK(result))
@@ -16,7 +16,7 @@ func handleLogicError(c *gin.Context, err error) bool {
if err == nil {
return false
}
return apiutil.AbortNotFoundIfMissing(c, err, "记录不存在")
return response.AbortNotFoundIfMissing(c, err, "记录不存在")
}
func versionParam(c *gin.Context) (string, bool) {
@@ -83,7 +83,7 @@ func GetConfigVersionHandler(c *gin.Context) {
// @Router /api/v1/d/config-versions/active [get]
func GetActiveConfigVersionHandler(c *gin.Context) {
version, err := GetActiveConfigVersion(c.Request.Context())
if apiutil.AbortNotFoundIfMissing(c, err, errNoActiveVersion) {
if response.AbortNotFoundIfMissing(c, err, errNoActiveVersion) {
return
}
c.JSON(http.StatusOK, response.OK(version))
@@ -16,7 +16,7 @@ func handleLogicError(c *gin.Context, err error) bool {
if err == nil {
return false
}
return apiutil.AbortNotFoundIfMissing(c, err, errOriginNotFound)
return response.AbortNotFoundIfMissing(c, err, errOriginNotFound)
}
// GetOrigins 列出全部源站。
@@ -16,7 +16,7 @@ func handleLogicError(c *gin.Context, err error) bool {
if err == nil {
return false
}
return apiutil.AbortNotFoundIfMissing(c, err, errProxyRouteNotFound)
return response.AbortNotFoundIfMissing(c, err, errProxyRouteNotFound)
}
// GetProxyRoutes 列出全部代理规则。
@@ -16,7 +16,7 @@ func handleLogicError(c *gin.Context, err error) bool {
if err == nil {
return false
}
return apiutil.AbortNotFoundIfMissing(c, err, "记录不存在")
return response.AbortNotFoundIfMissing(c, err, "记录不存在")
}
// GetCertificates 列出 TLS 证书。
@@ -1,35 +0,0 @@
// Copyright 2026 Arctel.net
// SPDX-License-Identifier: Apache-2.0
package apiutil
import (
"errors"
"Wavelet/pkg/response"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// AbortNotFoundIfMissing maps gorm.ErrRecordNotFound to 404; other errors to 400.
func AbortNotFoundIfMissing(c *gin.Context, err error, notFoundMsg string) bool {
if err == nil {
return false
}
if errors.Is(err, gorm.ErrRecordNotFound) {
response.AbortNotFound(c, notFoundMsg)
return true
}
response.AbortBadRequest(c, err.Error())
return true
}
// AbortBadRequestOnError writes a 400 for any non-nil error.
func AbortBadRequestOnError(c *gin.Context, err error) bool {
if err == nil {
return false
}
response.AbortBadRequest(c, err.Error())
return true
}
+1
View File
@@ -13,6 +13,7 @@ sidebar: false
### 🛠 修复
- 人机验证与健康检查去掉双路径:浏览器只请求 `/api/v1/cap/challenge` 与 `/api/v1/cap/redeem`,探针只保留 `GET /api/healthz`(`{"status":"ok"}`)。旧的 `/api/cap/*`、`/api/health` 与 `/healthz` 不再注册。
- Handler 把「记录不存在 → 404、其它错误 → 400」的分支改走上游 `response.AbortNotFoundIfMissing` / `AbortBadRequestOnError`,不再在 OpenFlare 里各写一份。
- 控制面 `server` 插件按限界上下文重排目录:去掉 `openflare/` 与 `router/v1` 嵌套;业务在 `domain/`(site/fleet/pages 等),共享内核在 `kernel/`(model/repository 与适配器),HTTP 装配在 `httpapi`。接口路径与表结构不变。
- `server` 插件把 stamp、of_* SQL 与 ClickHouse 迁入单一 `migrate/` 包,updater 提到 `server/updater/`;删除已停用的 76 条历史迁移。全新安装会写入 OpenFlare 定时任务与产品配置默认值,已 stamp 的升级库不重插。