自定义中间件编写
中间件是 Gin 请求处理链的核心组件,自定义中间件可灵活扩展功能。
中间件基本结构
Go
// 中间件签名
type HandlerFunc func(c *gin.Context)
// 基本格式
func myMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 前置处理
c.Next() // 调用后续处理
// 后置处理
}
}
认证中间件
Go
func authMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("Authorization")
if token == "" {
c.AbortWithStatusJSON(401, gin.H{
"code": 401,
"message": "未提供认证信息",
})
return
}
// 验证 token
claims, err := validateToken(token)
if err != nil {
c.AbortWithStatusJSON(401, gin.H{
"code": 401,
"message": "token 无效",
})
return
}
// 存储用户信息
c.Set("user_id", claims.UserID)
c.Set("role", claims.Role)
c.Next()
}
}
日志中间件
Go
func loggerMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
path := c.Request.URL.Path
method := c.Request.Method
c.Next()
duration := time.Since(start)
status := c.Writer.Status()
log.Printf("[%s] %s %s %d %v",
method, path, c.ClientIP(), status, duration)
}
}
CORS 中间件
Go
func corsMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
c.Header("Access-Control-Allow-Headers", "Content-Type, Authorization")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
}
}
请求限流中间件
Go
func rateLimitMiddleware(limit int) gin.HandlerFunc {
limiter := make(map[string]int)
mutex := sync.Mutex{}
return func(c *gin.Context) {
ip := c.ClientIP()
mutex.Lock()
count := limiter[ip]
if count >= limit {
mutex.Unlock()
c.AbortWithStatusJSON(429, gin.H{
"code": 429,
"message": "请求过于频繁",
})
return
}
limiter[ip] = count + 1
mutex.Unlock()
c.Next()
}
}
请求超时中间件
Go
func timeoutMiddleware(timeout time.Duration) gin.HandlerFunc {
return func(c *gin.Context) {
ctx, cancel := context.WithTimeout(c.Request.Context(), timeout)
defer cancel()
c.Request = c.Request.WithContext(ctx)
done := make(chan struct{})
go func() {
c.Next()
close(done)
}()
select {
case <-done:
// 正常完成
case <-ctx.Done():
c.AbortWithStatusJSON(504, gin.H{
"code": 504,
"message": "请求超时",
})
}
}
}
中间件注册方式
Go
func main() {
r := gin.New()
// 全局注册
r.Use(loggerMiddleware())
r.Use(corsMiddleware())
// 路由组注册
api := r.Group("/api")
api.Use(authMiddleware())
// 单路由注册
r.GET("/admin", authMiddleware(), adminHandler)
r.Run(":8080")
}
带参数中间件
Go
func rateLimit(limit int, window time.Duration) gin.HandlerFunc {
return func(c *gin.Context) {
// 使用 limit 和 window 参数
c.Next()
}
}
// 注册时传入参数
r.Use(rateLimit(100, time.Minute))
中间件获取用户信息
Go
func roleMiddleware(requiredRole string) gin.HandlerFunc {
return func(c *gin.Context) {
role, exists := c.Get("role")
if !exists {
c.AbortWithStatus(401)
return
}
if role != requiredRole {
c.AbortWithStatusJSON(403, gin.H{
"message": "权限不足",
})
return
}
c.Next()
}
}
// 需先经过 authMiddleware 设置 role
adminGroup := r.Group("/admin")
adminGroup.Use(authMiddleware())
adminGroup.Use(roleMiddleware("admin"))
中间件注册顺序影响执行顺序,认证类放前,日志类放最前或最后。
要点总结
- 中间件返回
gin.HandlerFunc函数 c.Next()调用后续处理,c.Abort()终止c.Set()存储数据,c.Get()获取数据- 全局注册用
r.Use(),路由组用group.Use() - 可通过闭包传递参数给中间件
📝 发现内容有误?点击此处直接编辑