gin自定義中間件解決requestBody不可重讀(請(qǐng)求體取值)
使用中間件
注意,這個(gè)中間件,需要在第一個(gè)執(zhí)行。
問(wèn)題復(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】會(huì)取不到值
其他方式解決方案
方法一:使用context.ShouldBindBodyWith() (推薦)
個(gè)人推薦這個(gè)方法,更簡(jiǎn)單
官網(wǎng)詳細(xì)文檔:將 request body 綁定到不同的結(jié)構(gòu)體中 | 示例 |《Gin 框架中文文檔 1.7》| Go 技術(shù)論壇 (learnku.com)
用例:
ctx.ShouldBindBodyWith(&test,binding.JSON)
測(cè)試完整代碼:
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對(duì)象:var data model.Post
c.BindJSON(&data)
寫入:
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(data))
參考總結(jié)方式
r := gin.Default() // 注冊(cè)中間件,使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方法,都會(huì)新生成一個(gè)io.ReadCloser,但是底層的byte數(shù)據(jù),都是all變量緩存的。 context.Request.Body = body context.Next() })
以上就是gin自定義中間件解決requestBody不可重讀(請(qǐng)求體取值)的詳細(xì)內(nèi)容,更多關(guān)于gin requestBody請(qǐng)求體取值的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解golang中的結(jié)構(gòu)體編解碼神器Mapstructure庫(kù)
mapstructure是GO字典(map[string]interface{})和Go結(jié)構(gòu)體之間轉(zhuǎn)換的編解碼工具,這篇文章主要為大家介紹一下Mapstructure庫(kù)的相關(guān)使用,希望對(duì)大家有所幫助2023-09-09Go中基本數(shù)據(jù)類型和字符串表示之間轉(zhuǎn)換詳解
這篇文章主要為大家詳細(xì)介紹了Go中基本數(shù)據(jù)類型和字符串表示之間轉(zhuǎn)換的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01Go語(yǔ)言HTTP請(qǐng)求流式寫入body的示例代碼
這篇文章主要介紹了Go語(yǔ)言HTTP請(qǐng)求流式寫入body,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06golang通用的grpc?http基礎(chǔ)開(kāi)發(fā)框架使用快速入門
這篇文章主要為大家介紹了golang通用的grpc?http基礎(chǔ)開(kāi)發(fā)框架使用快速入門詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09Go語(yǔ)言實(shí)現(xiàn)的最簡(jiǎn)單數(shù)獨(dú)解法
前面給大家介紹過(guò)使用javascript實(shí)現(xiàn)的簡(jiǎn)單的數(shù)獨(dú)解法,小伙伴們都非常喜歡,今天我們?cè)賮?lái)分享一則go語(yǔ)言實(shí)現(xiàn)的簡(jiǎn)單的數(shù)獨(dú)解法,有需要的小伙伴來(lái)參考下。2015-03-03RabbitMQ延時(shí)消息隊(duì)列在golang中的使用詳解
延時(shí)隊(duì)列常使用在某些業(yè)務(wù)場(chǎng)景,使用延時(shí)隊(duì)列可以簡(jiǎn)化系統(tǒng)的設(shè)計(jì)和開(kāi)發(fā)、提高系統(tǒng)的可靠性和可用性、提高系統(tǒng)的性能,下面我們就來(lái)看看如何在golang中使用RabbitMQ的延時(shí)消息隊(duì)列吧2023-11-11