Gin 路由以及中间件

路由&&中间件

    • 路由重定向
    • 分组路由
    • 全局中间件
    • 单个路由中间件
    • 群组中间件
    • 中间件实践

路由重定向

r:=gin.Default()
r.GET("/baidu", func(c *gin.Context) {
	c.Redirect(http.StatusMovedPermanently, "https://baidu.com")
})
r.Run(":8089")

分组路由

分组路由使代码逻辑更加模块化,同时也易于定义中间件的使用范围

v1 := router.Group("/v1")

v1.GET("/login", func(c *gin.Context) {
    c.String(http.StatusOK, "v1 login")
})

v2 := router.Group("/v2")

v2.GET("/login", func(c *gin.Context) {
    c.String(http.StatusOK, "v2 login")
})

全局中间件

先定义一个中间件函数:

func MiddleWare() gin.HandlerFunc {
    return func(c *gin.Context) {
        fmt.Println("before middleware")
        c.Set("request", "clinet_request")
        c.Next()
        fmt.Println("before middleware")
    }
}

该函数只会给c上下文添加一个属性,并赋值。后面的路由处理器,可以根据被中间件装饰后提取其值。需要注意,虽然名为全局中间件,只要是在注册中间件的过程之前设置的路由,将不会受注册的中间件所影响。只有注册了中间件以下代码的路由函数规则,才会被中间件装饰

router.Use(MiddleWare())
{
    router.GET("/middleware", func(c *gin.Context) {
        request := c.MustGet("request").(string)
        req, _ := c.Get("request")
        c.JSON(http.StatusOK, gin.H{
            "middile_request": request,
            "request": req,
        })
    })
}

使用router装饰中间件,然后在/middlerware即可读取request的值,注意在router.Use(MiddleWare())代码以上的路由函数,将不会有被中间件装饰的效果。

使用花括号包含被装饰的路由函数只是一个代码规范,即使没有被包含在内的路由函数,只要使用router进行路由,都等于被装饰了。想要区分权限范围,可以使用组返回的对象注册中间件。

# curl  http://127.0.0.1:8000/middleware
{"middile_request":"clinet_request","request":"clinet_request"}

如果没有注册就使用 MustGet 方法读取c的值将会抛错,可以使用 Get 方法取而代之

上面的注册装饰方式,会让所有下面所写的代码都默认使用 router 注册过的中间件

单个路由中间件

当然,gin也提供了针对指定的路由函数进行注册。

router.GET("/before", MiddleWare(), func(c *gin.Context) {
    request := c.MustGet("request").(string)
    c.JSON(http.StatusOK, gin.H{
        "middile_request": request,
    })
})

把上述代码写在 router.Use(Middleware())之前,同样 /before 被装饰了中间件

群组中间件

群组的中间件也类似,只要在对应的群组路由上注册中间件函数即可:

authorized := router.Group("/", MyMiddelware())
// 或者这样用:
authorized := router.Group("/")
authorized.Use(MyMiddelware())
{
    authorized.POST("/login", loginEndpoint)
}

群组可以嵌套,因为中间件也可以根据群组的嵌套规则嵌套

中间件实践

下面实现一个简易的鉴权中间件

router.GET("/auth/signin", func(c *gin.Context) {
    cookie := &http.Cookie{
        Name:     "session_id",
        Value:    "123",
        Path:     "/",
        HttpOnly: true,
    }
    http.SetCookie(c.Writer, cookie)
    c.String(http.StatusOK, "Login successful")
})

router.GET("/home", AuthMiddleWare(), func(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{"data": "home"})
})

登录函数会设置一个session_id的cookie,注意这里需要指定path为/,不然gin会自动设置cookie的path为/auth,一个特别奇怪的问题。/home的逻辑很简单,使用中间件AuthMiddleWare注册之后,将会先执行AuthMiddleWare的逻辑,然后才到/home的逻辑

AuthMiddleWare的代码如下:

func AuthMiddleWare() gin.HandlerFunc {
    return func(c *gin.Context) {
        if cookie, err := c.Request.Cookie("session_id"); err == nil {
            value := cookie.Value
            fmt.Println(value)
            if value == "123" {
                c.Next()
                return
            }
        }
        c.JSON(http.StatusUnauthorized, gin.H{
            "error": "Unauthorized",
        })
        c.Abort()
        return
    }
}

从上下文的请求中读取cookie,然后校对cookie,如果有问题,则终止请求,直接返回,这里使用了c.Abort()方法

♥ 喜 欢 请 点 赞 哟 ♥
(●ˇ∀ˇ●)

你可能感兴趣的:(Go)