gin自定義中間件解決requestBody不可重讀(請求體取值)
使用中間件
注意,這個中間件,需要在第一個執(zhí)行。
問題復(fù)現(xiàn)
type Test struct { Test string `json:"test"` } func main() { ginServer := gin.Default() ginServer.POST("/test", func(ctx *gin.Context) { //中間件取值 var test Test ctx.BindJSON(&test) fmt.Printf("inteceptor %v\n", test) ctx.Next() }, func(ctx *gin.Context) { //controller取值 var test Test ctx.BindJSON(&test) fmt.Printf("controller %v\n", test) }) }
結(jié)果
【中間件】從request.body里取值后,【controller】會取不到值
其他方式解決方案
方法一:使用context.ShouldBindBodyWith() (推薦)
個人推薦這個方法,更簡單
官網(wǎng)詳細(xì)文檔:將 request body 綁定到不同的結(jié)構(gòu)體中 | 示例 |《Gin 框架中文文檔 1.7》| Go 技術(shù)論壇 (learnku.com)
用例:
ctx.ShouldBindBodyWith(&test,binding.JSON)
測試完整代碼:
type Test struct { Test string `json:"test"` } func main() { ginServer := gin.Default() ginServer.POST("/test", func(ctx *gin.Context) { //中間件取值 var test Test //修改此處 ctx.ShouldBindBodyWith(&test, binding.JSON) fmt.Printf("inteceptor %v\n", test) ctx.Next() }, func(ctx *gin.Context) { //controller取值 var test Test //修改此處 ctx.ShouldBindBodyWith(&test, binding.JSON) fmt.Printf("controller %v\n", test) }) }
方法二:使用context.Set()/Get()
也可以使用【Session】或者其他方式完成,思路就是取完又存
具體詳看:
//中間件存值 func(ctx *gin.Context) { var test Test ctx.BindJSON(&test) ctx.Set("test", test) ctx.Next() } //controller取值 func(ctx *gin.Context) { var test Test value, _ := ctx.Get("test") test=value.(Test) fmt.Printf("controller %v\n", test) }
方法三:讀取body內(nèi)容
思路同樣是取完又存
讀?。?/p>
data, _ := ioutil.ReadAll(c.Request.Body)
bind對象:var data model.Post
c.BindJSON(&data)
寫入:
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(data))
參考總結(jié)方式
r := gin.Default() // 注冊中間件,使body可以重復(fù)讀取 r.Use(func(context *gin.Context) { all, err := context.GetRawData() // 讀取body的內(nèi)容 if err != nil { log.Fatal(err) } // 重寫 GetBody 方法,以便后續(xù)的其他操作 context.Request.GetBody = func() (io.ReadCloser, error) { context.Request.Body = io.NopCloser(bytes.NewBuffer(all)) buffer := bytes.NewBuffer(all) closer := io.NopCloser(buffer) return closer, nil } body, _ := context.Request.GetBody() // 每次調(diào)用GetBody方法,都會新生成一個io.ReadCloser,但是底層的byte數(shù)據(jù),都是all變量緩存的。 context.Request.Body = body context.Next() })
以上就是gin自定義中間件解決requestBody不可重讀(請求體取值)的詳細(xì)內(nèi)容,更多關(guān)于gin requestBody請求體取值的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解golang中的結(jié)構(gòu)體編解碼神器Mapstructure庫
mapstructure是GO字典(map[string]interface{})和Go結(jié)構(gòu)體之間轉(zhuǎn)換的編解碼工具,這篇文章主要為大家介紹一下Mapstructure庫的相關(guān)使用,希望對大家有所幫助2023-09-09Go中基本數(shù)據(jù)類型和字符串表示之間轉(zhuǎn)換詳解
這篇文章主要為大家詳細(xì)介紹了Go中基本數(shù)據(jù)類型和字符串表示之間轉(zhuǎn)換的相關(guān)知識,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01golang通用的grpc?http基礎(chǔ)開發(fā)框架使用快速入門
這篇文章主要為大家介紹了golang通用的grpc?http基礎(chǔ)開發(fā)框架使用快速入門詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09