update: 整理项目结构 重写中间件 提高复用性

This commit is contained in:
2025-09-26 12:29:57 +08:00
parent 5daf6df318
commit d15352a18b
9 changed files with 430 additions and 324 deletions

View File

@@ -0,0 +1,31 @@
package middleware
import (
"log/slog"
"time"
"github.com/gin-gonic/gin"
)
// Logger 使用 slog 输出结构化访问日志
func Logger(logger *slog.Logger) gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
path := c.Request.URL.Path
raw := c.Request.URL.RawQuery
c.Next()
if raw != "" { path = path + "?" + raw }
latency := time.Since(start)
status := c.Writer.Status()
logger.Info("HTTP请求",
"req_id", GetReqID(c),
"method", c.Request.Method,
"path", path,
"status", status,
"latency_ms", latency.Milliseconds(),
"size", c.Writer.Size(),
"ip", c.ClientIP(),
"ua", c.GetHeader("User-Agent"),
)
}
}

View File

@@ -0,0 +1,30 @@
package middleware
import (
"log/slog"
"net/http"
"runtime/debug"
"github.com/gin-gonic/gin"
)
// Recovery 捕获 panic 并记录堆栈信息
func Recovery(logger *slog.Logger) gin.HandlerFunc {
return func(c *gin.Context) {
defer func() {
if rcv := recover(); rcv != nil {
logger.Error("发生Panic",
"req_id", GetReqID(c),
"error", rcv,
"stack", string(debug.Stack()),
"path", c.Request.URL.Path,
)
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
"error": "内部服务器错误",
"req_id": GetReqID(c),
})
}
}()
c.Next()
}
}

View File

@@ -0,0 +1,32 @@
package middleware
import (
"fmt"
"sync/atomic"
"github.com/gin-gonic/gin"
)
const RequestIDKey = "reqID"
var globalReqID atomic.Int64
// RequestID 生成自增的请求 ID 并注入上下文及响应头
func RequestID() gin.HandlerFunc {
return func(c *gin.Context) {
id := globalReqID.Add(1)
c.Set(RequestIDKey, id)
c.Writer.Header().Set("X-Request-ID", fmt.Sprintf("%d", id))
c.Next()
}
}
// GetReqID 从上下文中获取请求 ID
func GetReqID(c *gin.Context) int64 {
if v, ok := c.Get(RequestIDKey); ok {
if id, ok2 := v.(int64); ok2 {
return id
}
}
return 0
}