gin获取get和post以及json所有参数获取
描述:
- http接口,一般有如下几种传参:get、post、 post application/json 的模式,当然还有post传xml模式,只是用的人比较少
- 一般我们在使用中间件的时候,需要把所有的参数给获取到,然后进行加密验签。需要对所有的参数进行统一验证。
问题
- 我在使用gin框架的context的时候,发现有如下方法:ShouldBind 可用于GET的绑定参数,ShouldBindJSON和ShouldBind一样,只是增加了一个格式参数,ShouldBindWith同json。后发现ShouldBind类型的函数只能使用一次,第二次再绑定的时候就无法使用了,
如:var tmpParams = make(map[string]string) err2 := ctx.ShouldBind(&tmpParams) if err2 != nil { fmt.Println(err2) } fmt.Printf("-----tmpParams: %v \n",tmpParams ) var tmpParams2 = make(map[string]string) err3 := ctx.ShouldBind(&tmpParams2) if err3 != nil { fmt.Println(err3) } fmt.Printf("-----tmpParams2: %v \n",tmpParams2 )
打印后发现,tmpParams正常,tmpParams2没有值。
这对于我们写中间件的人来说是绝对不能接受的,不能因为中间件取值了,其它接口内部就无法使用ShouldBind来接受参数。
解决问题
最终发现我的github.com/gin-gonic/gin
版本过低,是1.6.3版本,然后升级到1.8.1发现,可以重复绑定了问题解决
整理了下代码
package RequestParse
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/sirupsen/logrus"
"strings"
"sync"
)
type RequestHttp struct {
ctx *gin.Context
Params map[string]interface{}
lock sync.Mutex
}
func Instance(ctx *gin.Context) *RequestHttp {
return &RequestHttp{
ctx: ctx,
Params: map[string]interface{}{},
}
}
//获取默认参数列表
func (r *RequestHttp) GetDefaultParams() map[string]interface{} {
ctx := r.ctx
method := ctx.Request.Method
url := ctx.Request.URL.Path
return map[string]interface{}{
"method": method,
"url": url,
"remoteAddr": r.GetRemoteAddr(),
"params": r.RequestParams(),
"requestID": r.GetHeaderByKey("request-id"),
"status": ctx.Writer.Status(),
"userAgent": ctx.GetHeader("User-Agent"),
}
}
//获取kname
func (r *RequestHttp) GetHeaderByKey(kname string) string {
return r.ctx.Request.Header.Get(kname)
}
//获取remoteAddr
func (r *RequestHttp) GetRemoteAddr() string {
remoteAddr := r.ctx.Request.Header.Get("Remote_addr")//远程调用
if remoteAddr == "" {
remoteAddr = r.ctx.Request.Header.Get("X-Forward-For")
}
return remoteAddr
}
//获取参数集合
func (r *RequestHttp) RequestParams() string {
ctx := r.ctx
bindParams := map[string]interface{}{}
if ctx.Request.Method == "POST" {
contextType := ctx.Request.Header.Get("Content-Type")
if contextType == "application/json" {
err := ctx.ShouldBindBodyWith(&bindParams, binding.JSON)
if err != nil {//报错
logrus.Errorf("nyx_request_mid_error %v,err: %v \n", bindParams, err)
return ""
}
if len(bindParams) > 0 {
for k, v := range bindParams {
r.Add(k, v)
}
}
} else {
_ = ctx.Request.ParseMultipartForm(32 << 20)
if len(ctx.Request.PostForm) > 0 {
for k, v := range ctx.Request.PostForm {
r.Add(k, v[0])
}
}
}
} else {
var tmpParams = make(map[string]string)
err2 := ctx.ShouldBind(&tmpParams)
if err2 != nil {
fmt.Println(err2)
logrus.Errorf("nyx_request_mid_error %v,err: %v \n", bindParams, err2)
return ""
}
for k, v := range tmpParams {
r.Add(k, v)
}
}
fmt.Printf("------params:%v \n",r.JoinParamsStr())
return r.JoinParamsStr()
}
//添加参数
func (r *RequestHttp) AddParams(m map[string]interface{}) {
if len(m) <= 0 {
return
}
for k, v := range m {
r.Add(k, v)
}
}
func (r *RequestHttp) JoinParamsStr() string {
var params []string
if len(r.Params) > 0 {
for k,v := range r.Params {
params = append(params, fmt.Sprintf("%s=%v", k, v))
}
}
return strings.Join(params, "&")
}
//添加参数
func (r *RequestHttp) Add(key string, value interface{}) {
r.lock.Lock()
r.Params[key] = value
r.lock.Unlock()
}
//删除参数
func (r *RequestHttp) Delete(key string) {
r.lock.Lock()
if _,ok := r.Params[key]; ok {
delete(r.Params, key)
}
r.lock.Unlock()
}
以上代码包含、post、get、以及json的方式的参数获取方法。中间件封装的时候可以借鉴。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: