feat: 完善后端脚手架基础能力
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"skeleton/modules/auth"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterPublic(registerAuthPublicRoutes)
|
||||
RegisterPrivate(registerAuthPrivateRoutes)
|
||||
}
|
||||
|
||||
func registerAuthPublicRoutes(r *gin.RouterGroup) {
|
||||
ctrl := auth.NewController()
|
||||
group := r.Group("/auth")
|
||||
group.POST("/register", ctrl.Register)
|
||||
group.POST("/login", ctrl.Login)
|
||||
group.POST("/refresh", ctrl.Refresh)
|
||||
}
|
||||
|
||||
func registerAuthPrivateRoutes(r *gin.RouterGroup) {
|
||||
ctrl := auth.NewController()
|
||||
r.POST("/auth/logout", ctrl.Logout)
|
||||
}
|
||||
+60
-13
@@ -1,29 +1,76 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"skeleton/database"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type systemResponse struct {
|
||||
Code int `json:"code" example:"200"`
|
||||
Message string `json:"message"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
type healthData struct {
|
||||
Status string `json:"status"`
|
||||
Database string `json:"database"`
|
||||
Redis string `json:"redis"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
RegisterPublic(registerHealthRoutes)
|
||||
}
|
||||
|
||||
func registerHealthRoutes(r *gin.RouterGroup) {
|
||||
r.GET("/ping", func(ctx *gin.Context) {
|
||||
ctx.JSON(http.StatusOK, gin.H{
|
||||
"code": 200,
|
||||
"message": "pong",
|
||||
"data": nil,
|
||||
})
|
||||
})
|
||||
r.GET("/ping", ping)
|
||||
r.GET("/health", health)
|
||||
}
|
||||
|
||||
r.GET("/health", func(ctx *gin.Context) {
|
||||
ctx.JSON(http.StatusOK, gin.H{
|
||||
"code": 200,
|
||||
"message": "ok",
|
||||
"data": nil,
|
||||
})
|
||||
// ping godoc
|
||||
// @Summary 服务连通性检查
|
||||
// @Tags system
|
||||
// @Produce json
|
||||
// @Success 200 {object} systemResponse
|
||||
// @Router /ping [get]
|
||||
func ping(ctx *gin.Context) {
|
||||
ctx.JSON(http.StatusOK, gin.H{
|
||||
"code": 200,
|
||||
"message": "pong",
|
||||
"data": nil,
|
||||
})
|
||||
}
|
||||
|
||||
// health godoc
|
||||
// @Summary 服务健康检查
|
||||
// @Tags system
|
||||
// @Produce json
|
||||
// @Success 200 {object} systemResponse{data=healthData}
|
||||
// @Failure 503 {object} systemResponse{data=healthData}
|
||||
// @Router /health [get]
|
||||
func health(ctx *gin.Context) {
|
||||
checkCtx, cancel := context.WithTimeout(ctx.Request.Context(), 2*time.Second)
|
||||
defer cancel()
|
||||
|
||||
data := healthData{Status: "ok", Database: "up", Redis: "disabled"}
|
||||
status := http.StatusOK
|
||||
if err := database.Ping(checkCtx); err != nil {
|
||||
data.Status = "degraded"
|
||||
data.Database = "down"
|
||||
status = http.StatusServiceUnavailable
|
||||
}
|
||||
if client := database.GetRedisClient(); client != nil {
|
||||
data.Redis = "up"
|
||||
if err := client.Ping(checkCtx); err != nil {
|
||||
data.Status = "degraded"
|
||||
data.Redis = "down"
|
||||
status = http.StatusServiceUnavailable
|
||||
}
|
||||
}
|
||||
|
||||
ctx.JSON(status, gin.H{"code": status, "message": data.Status, "data": data})
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"skeleton/routes/ws"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
@@ -24,11 +26,22 @@ func SetupRoutes(cfg *config.Config) *gin.Engine {
|
||||
r.MaxMultipartMemory = 100 << 20 // 100 MB
|
||||
|
||||
// 添加自定义中间件
|
||||
r.Use(middlewares.RequestID())
|
||||
if cfg.Observability.TracingEnabled {
|
||||
r.Use(otelgin.Middleware(cfg.Observability.TracingService))
|
||||
}
|
||||
if cfg.Observability.MetricsEnabled {
|
||||
r.Use(middlewares.Metrics())
|
||||
}
|
||||
r.Use(middlewares.CORS()) // CORS跨域处理(需要在其他中间件之前)
|
||||
r.Use(middlewares.GinLogger()) // 结构化日志
|
||||
r.Use(middlewares.GinRecovery()) // 异常恢复
|
||||
r.Use(middlewares.ErrorLogging()) // 错误响应日志(用于记录逻辑异常)
|
||||
|
||||
if cfg.Observability.MetricsEnabled {
|
||||
r.GET(cfg.Observability.MetricsPath, gin.WrapH(promhttp.Handler()))
|
||||
}
|
||||
|
||||
// API 路由组
|
||||
api := r.Group("/api")
|
||||
|
||||
|
||||
+8
-2
@@ -1,8 +1,14 @@
|
||||
package ws
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
import (
|
||||
wsModule "skeleton/modules/ws"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ApplyWebSocketRoutes WebSocket路由挂载点
|
||||
func ApplyWebSocketRoutes(r *gin.RouterGroup) {
|
||||
_ = r
|
||||
hub := wsModule.NewHub()
|
||||
controller := wsModule.NewController(hub)
|
||||
r.GET("/ws", controller.Connect)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user