網頁

2021/11/10

Golang Gin Engine.HandleContext() 用途

Gin Engine.HandleContext(c *Context)的作用為路由重新導向(Router redirect)。


例如下面定義了兩個endpoint GET|/helloGET|/hi

GET|/hello的handler func中利用Context.Request.URL.Path設定重新導向路徑為/hiContext.Request.URL.RawQuery設定url請求參數,最後調用Engine.HandleContext(c *Context)進行重新導向。

package main

import (
    "fmt"

    "github.com/gin-gonic/gin"
)

func main() {
    router := gin.New()

    router.GET("/hello", func(c *gin.Context) {
        fmt.Println("hello")

        c.Request.URL.Path = "/hi" // redirect path
        c.Request.URL.RawQuery = "name=john" // url query string
        router.HandleContext(c) // Router redirect
    })

    router.GET("/hi", func(c *gin.Context) {
        fmt.Println("hi")

        name := c.Query("name")
        message := fmt.Sprintf("hi, %s", name)
        c.JSON(200, gin.H{"message": message})
    })
    router.Run()
}

啟動Go使用curl命令發送GET request到http://localhost:8080/hello返回結果如下。

$ curl -X GET "http://localhost:8080/hello"
{"message":"hi, john"}


注意Engine.HandleContext(c *Context)重新導向時會重設Context,也就裡面的key-value,param等會被清除,原始碼如下。

gin.go#L453

...
func (engine *Engine) HandleContext(c *Context) {
    oldIndexValue := c.index
    c.reset() // reset Context
    engine.handleHTTPRequest(c)

    c.index = oldIndexValue
}
...

context.go#L87

...
func (c *Context) reset() {
    c.Writer = &c.writermem
    c.Params = c.Params[0:0]
    c.handlers = nil
    c.index = -1

    c.fullPath = ""
    c.Keys = nil
    c.Errors = c.Errors[0:0]
    c.Accepted = nil
    c.queryCache = nil
    c.formCache = nil
    *c.params = (*c.params)[0:0]
}
...

例如下面在/hello的handler func中把name=john放入c Context,但重新導向到/hi取得的是nil

package main

import (
    "fmt"

    "github.com/gin-gonic/gin"
)

func main() {
    router := gin.New()

    router.GET("/hello", func(c *gin.Context) {
        fmt.Println("hello")

        c.Set("name", "john") // set name=john

        c.Request.URL.Path = "/hi"
        router.HandleContext(c)
    })

    router.GET("/hi", func(c *gin.Context) {
        fmt.Println("hi")

        name, _ := c.Get("name") // name is nil

        c.JSON(200, gin.H{"message": name})
    })
    router.Run()
}

curl發送請求結果。

$ curl -X GET "http://localhost:8080/hello"
{"message":null}


沒有留言:

張貼留言