golang gin中间件中重复绑定获取请求body中参数,json请求格式

文章介绍了在Gin框架中,多次调用ShouldBind或ShouldBindJSON方法时出现EOF错误的原因,即请求体数据流被多次读取。为了解决这个问题,提出了一个解决方案,即在第一次调用后保存请求体,然后重置Request.Body,确保后续绑定操作能正常读取。示例代码展示了如何实现这一过程。
摘要由CSDN通过智能技术生成

你是不是在中间件里面ShouldBind报错EOF

  • 在 Gin 框架中,当多次调用 ShouldBind() 或 ShouldBindJSON() 方法时,会导致请求体的数据流被读取多次,从而出现 “EOF” 错误。

  • 这是因为在 HTTP 请求中,请求体的数据流是按顺序读取的。每次调用 ShouldBind() 或 ShouldBindJSON() 方法都会尝试读取请求体的数据流,但在第一次读取后,数据流已经被消耗完毕,所以后续的读取操作将会返回 “EOF” 错误。

  • 为了避免这个问题,你可以在第一次调用 ShouldBind() 或 ShouldBindJSON() 方法后,将请求体的数据流保存下来,并重新设置到 Request.Body 中,以便后续的绑定操作可以重新读取请求体的数据。

  • 参考这篇文章改造的代码:https://learnku.com/articles/69068

下面是我的解决代码

package middleware

import (
	"bytes"
	"fmt"
	"io"
	"xxxx/common/global"
	"strings"

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

// 获取参数集合
func RequestParams(ctx *gin.Context) {
	bindParams := map[string]any{}
	if ctx.Request.Method == "POST" {
		contextType := ctx.Request.Header.Get("Content-Type")
		requestBody, err := ctx.GetRawData()
		if err != nil {
			global.Logger.Errorf("GetRawData,err: %v ", err)
			return
		}
		// 重置请求体,以便后续的中间件和处理程序可以正常读取
		ctx.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
		defer func() {
			ctx.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
		}()
		// 绑定参数
		if contextType == "application/json" {
			err := ctx.ShouldBind(&bindParams)
			if err != nil { // 报错
				global.Logger.Errorf("获取参数异常: %v ", err)
				return
			}
		} else {
			_ = ctx.Request.ParseMultipartForm(32 << 20)
			if len(ctx.Request.PostForm) > 0 {
				for k, v := range ctx.Request.PostForm {
					bindParams[k] = v[0]
				}
			}
		}
	}
	ctx.Set("RequestParams", bindParams)
}

func JoinParamsStr(ctx *gin.Context) string {
	params := ctx.GetStringMap("RequestParams")
	var newparams []string
	if len(params) > 0 {
		for k, v := range params {
			newparams = append(newparams, fmt.Sprintf("%s=%v", k, v))
		}
	}
	return strings.Join(newparams, "&")
}

func GetRequestParams(ctx *gin.Context) map[string]any {
	return ctx.GetStringMap("RequestParams")
}


router.go

// 引入中间件
r.Use(middleware.RequestParams)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值