gin自定義中間件解決requestBody不可重讀(請求體取值)
使用中間件
注意,這個(gè)中間件,需要在第一個(gè)執(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() (推薦)
個(gè)人推薦這個(gè)方法,更簡單
官網(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)容
思路同樣是取完又存
讀取:
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方法,都會新生成一個(gè)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-09
Go中基本數(shù)據(jù)類型和字符串表示之間轉(zhuǎn)換詳解
這篇文章主要為大家詳細(xì)介紹了Go中基本數(shù)據(jù)類型和字符串表示之間轉(zhuǎn)換的相關(guān)知識,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01
golang通用的grpc?http基礎(chǔ)開發(fā)框架使用快速入門
這篇文章主要為大家介紹了golang通用的grpc?http基礎(chǔ)開發(fā)框架使用快速入門詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
Go語言實(shí)現(xiàn)的最簡單數(shù)獨(dú)解法
前面給大家介紹過使用javascript實(shí)現(xiàn)的簡單的數(shù)獨(dú)解法,小伙伴們都非常喜歡,今天我們再來分享一則go語言實(shí)現(xiàn)的簡單的數(shù)獨(dú)解法,有需要的小伙伴來參考下。2015-03-03
RabbitMQ延時(shí)消息隊(duì)列在golang中的使用詳解
延時(shí)隊(duì)列常使用在某些業(yè)務(wù)場景,使用延時(shí)隊(duì)列可以簡化系統(tǒng)的設(shè)計(jì)和開發(fā)、提高系統(tǒng)的可靠性和可用性、提高系統(tǒng)的性能,下面我們就來看看如何在golang中使用RabbitMQ的延時(shí)消息隊(duì)列吧2023-11-11

