Golang gin 中間件類型

在 Gin 框架中,中間件是一種對請求進行預處理或攔截的機制。中間件可以用來實現很多功能,比如身份驗證、請求日誌記錄、請求參數驗證等。在 Gin 中,中間件可以是一個函數或一個結構體。

下面分別介紹這兩種中間件類型,並給出例子。

  1. 函數式中間件

函數式中間件是一個接受 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、遠程地址和處理時間等信息,並將它們輸出到日誌中。

  1. 結構體中間件

結構體中間件是一個實現了 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 響應。

  1. 多個函數式中間件組成的中間件鏈
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()。

  1. 分組中間件
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())

這個示例演示瞭如何使用分組中間件。分組中間件只會對分組中的路由生效,而不會對全局路由生效。

  1. 基於路由的中間件
func RouteMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        // ...
    }
}

// 使用基於路由的中間件
router := gin.Default()
router.GET("/", RouteMiddleware(), func(c *gin.Context) {
    // ...
})

  1. 基於 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 方法生效。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章