關於網路那些事...

網路行銷,SEO,網路趨勢,教學文章,網頁設計,生活時事

Gin - Middleware (中間件) 程式運作原理及用法教學

| Comments

Gin - Middleware (中間件) 程式運作原理及用法教學

在 Web 應用及開發中,一個完整的請求會包含客戶端請求,伺服器端接收及處理,返回內容給結果。

在真實的場景中,在這些流程還會有更複雜的功能,例如:權限管理,安全驗證及日誌等部分,因此在開發過程我們常要思考,如何更好的管理這些通用的功能,以套件的方式來進行開發,就可以很方便地進行對接及配置。

在這裡就要介紹Gin 的 Middleware (中間件)的運作方式及原理,如何透過 Middleware 來管理這些通用的一些服務。

Middleware 負責作用的位置如下:

Client 請求 <-> Go Http server <-> Middleware <-> Handle Function

Middleware 基本結構說明

在 Gin 的 Middleware 主要的結構如下:

type HandlerFunc func(*Context)

要用 use 調用 Middleware,在 Go 語言實踐的方式如下:

func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes {
    engine.RouterGroup.Use(middleware...)
    engine.rebuild404Handlers()
    engine.rebuild405Handlers()
    return engine
}

其實,在 Gin 架構本身有許多部分就是用 Middleware 設計,例如,gin.Default() 這個方法,就已經使用了 Middleware

engine.Use(Logger(), Recover())

例如, Logger() 負責日誌的部分,格式如下

func Logger() HandlerFunc{
    return LoggerWithConfig(LoggerCOnfig{})
}

對於 Recovery() 則是在我們服務發生錯誤時,會避免panic 並且返回 500 錯誤訊息。

如何自定義制定 Middleware

自定義 Middleware 主要須滿足以下兩個條件:

  • 函數 func
  • 返回 HandlerFunc

建立通用的 Middleware

舉例來說,這裡我們建立一個簡單的 middleware ,在每次請求過程都會 print 出 Helloworld

func RequestPrintHelloworld() gin.HandlerFunc {
    return func() {
    fmt.Println("Helloworld")
    }
}

接著我們就可以在代碼中使用這個 Middleware

func main() {
    engine := gin.Default()
  engine.Use(RequestPrintHelloworld())

  engine.GET('/home', func(context *gin.Context) {
    context.JSON(200, map[string]interface{}{
      "status":1,
      "msg":"success",
    }))
  })
}

特定路由套用Middleware

在前面的情況下,是所有的請求都會一律套用 Middleware,如果是權限驗證,則是有些需要,有些請求不需要套用 Middleware。

這裡可以先了解一下 Gin 的Http請求的部分,以 GET 方法來說,格式基本上如下:

func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
return group.handle("GET", relativePath, handlers)
}

可以看到,第一個參數是接口參數,第二個參數是 HandlerFunc,從這裡可以了解到,如果Middleware 需要套用到某些路由,則可以在第二個參數進行套用,例如:

engines := gin.Default()

engine.GET("/home", RequestPrintHelloworld(), func(context *gin.Context) {
    context.JSON(200, map[string]interface{}{
      "status":1,
      "msg":"success",
  }))
})

透過Middleware處理請求後的行為

前面我們提到,在 Middleware 的請求是在解析請求之前完成,但如果某些情況下,想要在請求處理結束後,再透過 Middleware 來處理,要怎麼做呢?

這時可以透過 context.Next 函數來處理請求後的行為。

context.Next 可以把請求處理流程差分為兩部分:

在使用 context.Next 之前的的訊息,會按照 Middleware 正常的流程進行處理,也就是在接口解析之前就會完成:

Client 請求 <-> Go Http server <-> Middleware <-> Handle Function

在 context.Next 之後的內容,則會在接口解析處理之後,透過Middleware 來處理。

也就是說,流程大致如下:

Client 請求 -> Go Http server -> Middleware(context.Next 之前)-> Handle Function 解析接口 -> Middleware(context.Next 之後) -> 返回訊息給 Client 

底下舉例

func RequestPrintHelloworld() gin.HandlerFunc {
    return func(context *gin.Context) {
    fmt.Println("Helloworld")
    
    fmt.Println("正常 Middleware 流程", context.Writer.Status())
    
    context.Next() //開始導向解析接口

    
    
    fmt.Println("接口解析及處理完成,並且取得狀態", context.Writer.Status())
    }
}

在我們接口來直接返回 404

engines := gin.Default()

engine.GET("/home", RequestPrintHelloworld(), func(context *gin.Context) {
  fmt.Println("路由解析 Handle Function 流程")
    context.JSON(404, map[string]interface{}{
      "status":0,
      "msg":"not found",
  }))
})

接著會看到打印出的內容為:

正常 Middleware 流程 200
路由解析 Handle Function 流程
接口解析及處理完成,並且取得狀態 404

這裡可以看到,一開始進入 Middleware 時,請求狀態是正常 200,接著進入 router 解析狀態碼,我們直接返回 404,接著在Middleware content.Next() 之後,取得的狀態碼為 404。

以上就是在 Gin 的 Middleware 的一些運作原理及應用方式。


聲明,近期發現有平台大量盜用文章內容,若您發現內文非來自關於網路那些事 [https://adon988.logdown.com](https://adon988.logdown.com) ,希望您與我聯繫 [https://www.facebook.com/ThinkingWebsite](https://www.facebook.com/ThinkingWebsite)
(本文章源自"關於網路那些事)

最後,如果你喜歡這篇文章,請幫忙點個讚



最新文章推薦

討論

comments powered by Disqus