使用中間件
gin的中間件分為三類:全局中間件、路由中間件、分組路由中間件。
全局中間件:注冊全局中間件之后注冊的路由才會生效,如果有一些不希望使用全局中間件的路由規則,注冊路由代碼要放在注冊全局中間件之前。
路由中間件:在注冊路由時傳入的中間件,只對當前路由規則生效。
分組路由中間件:在分組路由中注冊,對當前組下的全部路由生效。
func main() {
r := gin.New()
r.Use(gin.Logger())
r.GET("/benchmark", MyBenchLogger(), benchEndpoint)
authorized := r.Group("/")
authorized.Use(AuthRequired())
{
authorized.POST("/login", loginEndpoint)
testing := authorized.Group("testing")
testing.GET("/analytics", analyticsEndpoint)
}
r.Run(":8080")
}
以上代碼展示了中間件的注冊方式。r.Use(gin.Logger())
為全局中間件,這里使用的是gin提供的Logger中間件。r.GET("/benchmark", MyBenchLogger(), benchEndpoint)
使用了MyBenchLogger中間件,只有在訪問/benchmark時生效。authorized.Use(AuthRequired())
使用了AuthRequired中間件,在訪問/login和/testing/analytics時生效,注意代碼中的嵌套路由。
自定義中間件
自定義gin中間件有兩種寫法。第一種:定義一個方法接收一個*gin.Context類型的參數,和handler的寫法是一樣的。第二種:定義一個無參的方法,返回值為HandlerFunc類型。代碼如下:
// 第一種
func DemoMiddleware(c *gin.Context) {
fmt.Println("DemoMiddleware")
c.Next()
}
// 第二種
func Demo1Middleware() gin.HandlerFunc {
return func(c *gin.Context) {
fmt.Println("Demo1Middleware")
c.Next()
}
}
在代碼中我們可以看到無論哪種方法定義的中間件都調用了c.Next()
將請求傳遞給請求鏈中下一個處理方法。中間件中我們還可以調用c.Abort(code)
提前結束請求,如下面認證中間件,token參數為空時將不在執行后續的處理方法。
func TokenAuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.Request.Header.Get("token")
if token == "" {
c.Abort()
return
}
c.Next()
}
}
func main() {
r := gin.Default()
r.GET("/auth", TokenAuthMiddleware(), func(c *gin.Context) {
c.JSON(200, gin.H{"message": "ok"})
})
r.Run(":9999")
}