基於gin的golang web開發:中間件


gin中間件(middleware)提供了類似於面向切面編程或路由攔截器的功能,可以在請求前和請求之後添加一些自定義邏輯。實際開發中有很多場景會用到中間件,例如:許可權驗證,快取,錯誤處理,日誌,事務等。

使用中間件

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")
}

文章出處:基於gin的golang web開發:中間件

Tags: