基于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: