Golang gin 中间件类型
在 Gin 框架中,中间件是一种对请求进行预处理或拦截的机制。中间件可以用来实现很多功能,比如身份验证、请求日志记录、请求参数验证等。在 Gin 中,中间件可以是一个函数或一个结构体。
下面分别介绍这两种中间件类型,并给出例子。
- 函数式中间件
函数式中间件是一个接受 gin.HandlerFunc 作为参数的函数。它可以在请求被处理之前或之后执行一些操作,比如记录日志、验证身份等。
下面是一个示例,演示如何实现一个记录请求日志的中间件:
func Logger() gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
// 处理请求
c.Next()
// 记录日志
latency := time.Since(start)
log.Printf("[%s] %s %s %v", c.Request.Method, c.Request.URL.Path, c.Request.RemoteAddr, latency)
}
}
// 使用中间件
router := gin.Default()
router.Use(Logger())
这个中间件会记录每个请求的 HTTP 方法、URL、远程地址和处理时间等信息,并将它们输出到日志中。
- 结构体中间件
结构体中间件是一个实现了 gin.HandlerFunc 接口的结构体。它可以包含一些成员变量和方法,用于在请求被处理之前或之后执行一些操作。
下面是一个示例,演示如何实现一个基于 JWT 的身份验证中间件
type AuthMiddleware struct {
JWTSecret []byte
}
func (m *AuthMiddleware) MiddlewareFunc() gin.HandlerFunc {
return func(c *gin.Context) {
// 从请求头中获取 token
tokenStr := c.GetHeader("Authorization")
if tokenStr == "" {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "missing token"})
return
}
// 解析 token
token, err := jwt.ParseWithClaims(tokenStr, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, error) {
return m.JWTSecret, nil
})
if err != nil {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid token"})
return
}
// 验证 token
if !token.Valid {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid token"})
return
}
// 将用户信息保存到上下文中
claims := token.Claims.(*jwt.StandardClaims)
c.Set("user_id", claims.Subject)
// 处理请求
c.Next()
}
}
// 使用中间件
router := gin.Default()
auth := &AuthMiddleware{JWTSecret: []byte("secret")}
router.Use(auth.MiddlewareFunc())
这个中间件会从请求头中获取 JWT token,并验证它是否合法。如果 token 验证通过,则将用户信息保存到上下文中,并让请求继续处理。如果验证不通过,则返回一个 HTTP 401 响应。
- 多个函数式中间件组成的中间件链
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// ...
}
}
func LoggerMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// ...
}
}
// 使用中间件链
router := gin.Default()
router.Use(LoggerMiddleware(), AuthMiddleware())
这个示例演示了如何使用多个函数式中间件组成的中间件链。中间件链中的中间件按照顺序依次执行,即 LoggerMiddleware() 执行完之后再执行 AuthMiddleware()。
- 分组中间件
func GroupAuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// ...
}
}
func GroupHandler() gin.HandlerFunc {
return func(c *gin.Context) {
// ...
}
}
// 使用分组中间件
router := gin.Default()
group := router.Group("/", GroupAuthMiddleware())
group.GET("/", GroupHandler())
这个示例演示了如何使用分组中间件。分组中间件只会对分组中的路由生效,而不会对全局路由生效。
- 基于路由的中间件
func RouteMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// ...
}
}
// 使用基于路由的中间件
router := gin.Default()
router.GET("/", RouteMiddleware(), func(c *gin.Context) {
// ...
})
- 基于 HTTP 方法的中间件
func GetMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// ...
}
}
// 使用基于 HTTP 方法的中间件
router := gin.Default()
router.GET("/", GetMiddleware(), func(c *gin.Context) {
// ...
})
这个示例演示了如何使用基于 HTTP 方法的中间件。基于 HTTP 方法的中间件只会对指定的 HTTP 方法生效,而不会对其他 HTTP 方法生效。
落霞与孤鹜齐飞,秋水共长天一色。