路由级中间件 #

一、路由级中间件概述 #

1.1 什么是路由级中间件 #

路由级中间件是应用于特定路由或路由分组的中间件,只对该路由或分组内的请求生效:

go
func main() {
    r := gin.New()
    
    // 全局中间件
    r.Use(gin.Logger())
    
    // 分组中间件
    api := r.Group("/api")
    api.Use(AuthMiddleware())
    {
        // 路由中间件
        api.GET("/admin", AdminMiddleware(), adminHandler)
    }
    
    r.Run()
}

1.2 中间件层级 #

text
请求
  ↓
全局中间件
  ↓
分组中间件
  ↓
路由中间件
  ↓
处理函数

二、分组中间件 #

2.1 基本用法 #

go
func main() {
    r := gin.New()
    
    // 需要认证的API分组
    api := r.Group("/api")
    api.Use(AuthMiddleware())
    {
        api.GET("/profile", getProfile)
        api.GET("/settings", getSettings)
    }
    
    // 公开API分组
    public := r.Group("/public")
    {
        public.GET("/info", getPublicInfo)
    }
    
    r.Run()
}

2.2 多级分组 #

go
func main() {
    r := gin.New()
    
    // API分组
    api := r.Group("/api")
    api.Use(LoggerMiddleware())
    {
        // v1版本
        v1 := api.Group("/v1")
        v1.Use(VersionMiddleware("v1"))
        {
            // 用户资源
            users := v1.Group("/users")
            users.Use(AuthMiddleware())
            {
                users.GET("", listUsers)
                users.GET("/:id", getUser)
            }
            
            // 公开资源
            public := v1.Group("/public")
            {
                public.GET("/info", getInfo)
            }
        }
        
        // v2版本
        v2 := api.Group("/v2")
        v2.Use(VersionMiddleware("v2"))
        {
            users := v2.Group("/users")
            users.Use(AuthMiddleware())
            users.Use(RateLimitMiddleware(100))
            {
                users.GET("", listUsersV2)
            }
        }
    }
    
    r.Run()
}

2.3 中间件继承 #

go
func main() {
    r := gin.New()
    
    // 父分组中间件会被子分组继承
    api := r.Group("/api")
    api.Use(Middleware1()) // 子分组会继承
    {
        // 继承Middleware1,并添加Middleware2
        users := api.Group("/users")
        users.Use(Middleware2())
        {
            // 继承Middleware1和Middleware2,并添加Middleware3
            admin := users.Group("/admin")
            admin.Use(Middleware3())
            {
                admin.GET("", adminHandler)
                // 执行顺序: Middleware1 → Middleware2 → Middleware3 → handler
            }
        }
    }
    
    r.Run()
}

三、单路由中间件 #

3.1 基本用法 #

go
func main() {
    r := gin.New()
    
    // 单个路由添加中间件
    r.GET("/profile", AuthMiddleware(), getProfile)
    
    // 多个中间件
    r.GET("/admin",
        AuthMiddleware(),
        AdminMiddleware(),
        adminHandler,
    )
    
    r.Run()
}

3.2 中间件链 #

go
func main() {
    r := gin.New()
    
    r.GET("/protected",
        func(c *gin.Context) {
            fmt.Println("中间件1")
            c.Next()
        },
        func(c *gin.Context) {
            fmt.Println("中间件2")
            c.Next()
        },
        func(c *gin.Context) {
            fmt.Println("处理函数")
            c.String(200, "ok")
        },
    )
    
    r.Run()
}

四、条件中间件 #

4.1 基于路径条件 #

go
func ConditionalMiddleware(pattern string, middleware gin.HandlerFunc) gin.HandlerFunc {
    return func(c *gin.Context) {
        if matched, _ := path.Match(pattern, c.Request.URL.Path); matched {
            middleware(c)
            return
        }
        c.Next()
    }
}

func main() {
    r := gin.New()
    
    // 只对/admin/*路径应用认证
    r.Use(ConditionalMiddleware("/admin/*", AuthMiddleware()))
    
    r.GET("/public", publicHandler)      // 不需要认证
    r.GET("/admin/users", adminHandler)  // 需要认证
    
    r.Run()
}

4.2 基于方法条件 #

go
func MethodMiddleware(method string, middleware gin.HandlerFunc) gin.HandlerFunc {
    return func(c *gin.Context) {
        if c.Request.Method == method {
            middleware(c)
            return
        }
        c.Next()
    }
}

func main() {
    r := gin.New()
    
    // 只对POST请求应用验证
    r.Use(MethodMiddleware("POST", ValidationMiddleware()))
    
    r.GET("/users", listUsers)    // 不需要验证
    r.POST("/users", createUser)  // 需要验证
    
    r.Run()
}

4.3 基于请求头条件 #

go
func HeaderMiddleware(header, value string, middleware gin.HandlerFunc) gin.HandlerFunc {
    return func(c *gin.Context) {
        if c.GetHeader(header) == value {
            middleware(c)
            return
        }
        c.Next()
    }
}

func main() {
    r := gin.New()
    
    // 只对特定版本的API应用中间件
    r.Use(HeaderMiddleware("API-Version", "v2", V2Middleware()))
    
    r.Run()
}

4.4 自定义条件 #

go
func When(condition func(*gin.Context) bool, middleware gin.HandlerFunc) gin.HandlerFunc {
    return func(c *gin.Context) {
        if condition(c) {
            middleware(c)
            return
        }
        c.Next()
    }
}

func main() {
    r := gin.New()
    
    // 自定义条件:只对特定用户应用中间件
    r.Use(When(func(c *gin.Context) bool {
        return c.GetHeader("X-User-Type") == "premium"
    }, PremiumMiddleware()))
    
    r.Run()
}

五、中间件组合 #

5.1 组合多个中间件 #

go
func Chain(middlewares ...gin.HandlerFunc) gin.HandlerFunc {
    return func(c *gin.Context) {
        for _, m := range middlewares {
            m(c)
            if c.IsAborted() {
                return
            }
        }
    }
}

func main() {
    r := gin.New()
    
    // 组合多个中间件
    r.GET("/protected",
        Chain(
            AuthMiddleware(),
            RateLimitMiddleware(100),
            PermissionMiddleware("read"),
        ),
        handler,
    )
    
    r.Run()
}

5.2 中间件工厂 #

go
type MiddlewareBuilder struct {
    middlewares []gin.HandlerFunc
}

func NewMiddlewareBuilder() *MiddlewareBuilder {
    return &MiddlewareBuilder{}
}

func (b *MiddlewareBuilder) Auth() *MiddlewareBuilder {
    b.middlewares = append(b.middlewares, AuthMiddleware())
    return b
}

func (b *MiddlewareBuilder) RateLimit(rps int) *MiddlewareBuilder {
    b.middlewares = append(b.middlewares, RateLimitMiddleware(rps))
    return b
}

func (b *MiddlewareBuilder) Permission(perm string) *MiddlewareBuilder {
    b.middlewares = append(b.middlewares, PermissionMiddleware(perm))
    return b
}

func (b *MiddlewareBuilder) Build() gin.HandlerFunc {
    return Chain(b.middlewares...)
}

func main() {
    r := gin.New()
    
    // 使用构建器创建中间件链
    middleware := NewMiddlewareBuilder().
        Auth().
        RateLimit(100).
        Permission("admin").
        Build()
    
    r.GET("/admin", middleware, adminHandler)
    
    r.Run()
}

六、实际应用场景 #

6.1 API版本控制 #

go
func main() {
    r := gin.New()
    
    v1 := r.Group("/api/v1")
    v1.Use(V1Middleware())
    {
        v1.GET("/users", listUsersV1)
    }
    
    v2 := r.Group("/api/v2")
    v2.Use(V2Middleware())
    v2.Use(DeprecationWarning())
    {
        v2.GET("/users", listUsersV2)
    }
    
    r.Run()
}

func DeprecationWarning() gin.HandlerFunc {
    return func(c *gin.Context) {
        c.Header("X-API-Deprecated", "true")
        c.Header("X-API-Sunset", "2024-12-31")
        c.Next()
    }
}

6.2 权限控制 #

go
func RequirePermission(permission string) gin.HandlerFunc {
    return func(c *gin.Context) {
        userRole, _ := c.Get("role")
        
        if !hasPermission(userRole.(string), permission) {
            c.AbortWithStatusJSON(403, gin.H{
                "code":    403,
                "message": "权限不足",
            })
            return
        }
        
        c.Next()
    }
}

func main() {
    r := gin.New()
    r.Use(AuthMiddleware())
    
    users := r.Group("/users")
    {
        users.GET("", RequirePermission("user:read"), listUsers)
        users.POST("", RequirePermission("user:create"), createUser)
        users.PUT("/:id", RequirePermission("user:update"), updateUser)
        users.DELETE("/:id", RequirePermission("user:delete"), deleteUser)
    }
    
    r.Run()
}

6.3 资源所有权验证 #

go
func ResourceOwner(resourceType string) gin.HandlerFunc {
    return func(c *gin.Context) {
        userId := c.GetString("userId")
        resourceId := c.Param("id")
        
        if !isOwner(userId, resourceType, resourceId) {
            c.AbortWithStatusJSON(403, gin.H{
                "code":    403,
                "message": "无权访问此资源",
            })
            return
        }
        
        c.Next()
    }
}

func main() {
    r := gin.New()
    r.Use(AuthMiddleware())
    
    r.GET("/posts/:id", ResourceOwner("post"), getPost)
    r.PUT("/posts/:id", ResourceOwner("post"), updatePost)
    r.DELETE("/posts/:id", ResourceOwner("post"), deletePost)
    
    r.Run()
}

6.4 功能开关 #

go
func FeatureFlag(feature string) gin.HandlerFunc {
    return func(c *gin.Context) {
        if !isFeatureEnabled(feature) {
            c.AbortWithStatusJSON(404, gin.H{
                "code":    404,
                "message": "功能未开放",
            })
            return
        }
        c.Next()
    }
}

func main() {
    r := gin.New()
    
    r.GET("/beta", FeatureFlag("beta_feature"), betaHandler)
    
    r.Run()
}

七、中间件调试 #

7.1 打印中间件链 #

go
func main() {
    r := gin.New()
    
    r.Use(func(c *gin.Context) {
        fmt.Println("全局中间件")
        c.Next()
    })
    
    api := r.Group("/api")
    api.Use(func(c *gin.Context) {
        fmt.Println("分组中间件")
        c.Next()
    })
    {
        api.GET("/test",
            func(c *gin.Context) {
                fmt.Println("路由中间件")
                c.Next()
            },
            func(c *gin.Context) {
                fmt.Println("处理函数")
                c.String(200, "ok")
            },
        )
    }
    
    // 打印路由信息
    routes := r.Routes()
    for _, route := range routes {
        fmt.Printf("%s %s\n", route.Method, route.Path)
    }
    
    r.Run()
}

7.2 中间件性能分析 #

go
func TimingMiddleware(name string) gin.HandlerFunc {
    return func(c *gin.Context) {
        start := time.Now()
        
        c.Next()
        
        duration := time.Since(start)
        log.Printf("[%s] took %v", name, duration)
    }
}

func main() {
    r := gin.New()
    
    r.Use(TimingMiddleware("global"))
    
    api := r.Group("/api")
    api.Use(TimingMiddleware("group"))
    {
        api.GET("/test", TimingMiddleware("route"), func(c *gin.Context) {
            c.String(200, "ok")
        })
    }
    
    r.Run()
}

八、总结 #

8.1 核心要点 #

要点 说明
分组中间件 Group().Use(middleware)
路由中间件 GET(path, middleware, handler)
中间件继承 子分组继承父分组中间件
条件中间件 根据条件决定是否执行

8.2 最佳实践 #

实践 说明
合理分层 全局、分组、路由级别
单一职责 每个中间件只做一件事
条件判断 使用条件中间件减少重复
权限控制 路由级权限验证

8.3 下一步 #

现在你已经掌握了路由级中间件,接下来让我们学习 自定义中间件,编写自己的中间件!

最后更新:2026-03-28