Skip to content

5.2 中间件开发 ​

中间件原理 ​

go
// 中间件本质
type Middleware func(http.Handler) http.Handler

// Gin 中间件
type GinMiddleware func(*gin.Context)

// 执行流程:
// 请求 -> Middleware1 -> Middleware2 -> Handler -> Middleware2 -> Middleware1 -> 响应

自定义中间件 ​

go
// 基础中间件
func SimpleMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        // 请求前
        c.Next()
        // 请求后
    }
}

// 日志中间件
func LoggerMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        start := time.Now()
        c.Next()
        latency := time.Since(start)
        fmt.Printf("[%s] %s %d %v\n", c.Request.Method, c.Request.URL.Path, c.Writer.Status(), latency)
    }
}

// 认证中间件
func AuthMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        token := c.GetHeader("Authorization")
        if token == "" {
            c.AbortWithStatusJSON(401, gin.H{"error": "未提供 token"})
            return
        }
        if !validateToken(token) {
            c.AbortWithStatusJSON(401, gin.H{"error": "token 无效"})
            return
        }
        c.Set("userID", "123")
        c.Next()
    }
}

// 限流中间件
func RateLimitMiddleware(maxReqs int, window time.Duration) gin.HandlerFunc {
    requests := make(map[string][]time.Time)
    return func(c *gin.Context) {
        ip := c.ClientIP()
        now := time.Now()
        // 清理过期记录
        var validReqs []time.Time
        for _, t := range requests[ip] {
            if t.After(now.Add(-window)) {
                validReqs = append(validReqs, t)
            }
        }
        // 检查是否超限
        if len(validReqs) >= maxReqs {
            c.AbortWithStatusJSON(429, gin.H{"error": "请求过于频繁"})
            return
        }
        validReqs = append(validReqs, now)
        requests[ip] = validReqs
        c.Next()
    }
}

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", "Origin, Content-Type, Authorization")
        if c.Request.Method == "OPTIONS" {
            c.AbortWithStatus(204)
            return
        }
        c.Next()
    }
}

// 使用 gin-contrib/cors
import "github.com/gin-contrib/cors"

config := cors.DefaultConfig()
config.AllowOrigins = []string{"http://localhost:3000"}
r.Use(cors.New(config))