go-zero
go-zero copied to clipboard
go-zero/gateway don't support form-data request params in v1.4.0
(因为内容比较多就中文写了) 我所使用的gozero框架是v1.4.0 我想问下gozero/gateway目录下的http网关,为什么不接受form-data类型的传参?
我写了一个demo程序,其中rpc的proto定义了:
message PingReq {
string ping = 1;
}
message PongRsp {
string pong = 1;
}
service Demo {
rpc Ping(PingReq) returns(PongRsp);
}
我使用postman对这个rpc服务的http网关进行调试:
- 在post方法中使用rawbody形式传json字符串是可以的
- 但是使用form-data会报错"400 EOF"
我可以保证在两次测试中,我仅修改了请求方的传参方式,没有修改任何代码。
经过自己对源码的研究,在go-zero/gateway/internal/requestparser.go中,找到了报错的原因:
// NewRequestParser creates a new request parser from the given http.Request and resolver.
func NewRequestParser(r *http.Request, resolver jsonpb.AnyResolver) (grpcurl.RequestParser, error) {
vars := pathvar.Vars(r)
params, err := httpx.GetFormValues(r)
if err != nil {
return nil, err
}
for k, v := range vars {
params[k] = v
}
body, ok := getBody(r)
if !ok {
return buildJsonRequestParser(params, resolver)
}
if len(params) == 0 {
return grpcurl.NewJSONRequestParser(body, resolver), nil
}
m := make(map[string]interface{})
if err := json.NewDecoder(body).Decode(&m); err != nil {
return nil, err
}
for k, v := range params {
m[k] = v
}
return buildJsonRequestParser(m, resolver)
}
上述代码我认为先进行了GetFormValues()将formdata的数据存入了params里,同时我也确认此时params已经拿到了我的传参数据,但是在接下来的逻辑中,会运行json.NewDecoder(body).Decode(&m),这一行中的Decode会报错。
经过我自己的测试,如果删去这行代码,并直接将params传参给buildJsonRequestParser(m, resolver),就可以正常解析form-data传参的参数,并且自己已经写demo确认过。
想问下作者这里是不是有bug,还是说有什么其他的考虑呢?迫切希望拨冗指点迷津
Would you please give a runnable demo to reproduce the problem? Thanks!
这是一个可以直接运行的程序,我把所需要的vendor依赖直接加在了里面。同时我也编译出了可以直接运行的二进制。
如果想复现上述问题,可以直接运行二进制,他会占用18888和18889端口。 然后只需要用postman进行post方式调用,即可复现问题:
curl --location --request POST 'http://0.0.0.0:18889/Ping' --form 'ping="hello"'
请问有解决吗?还是一定需要使用api服务去获取 form-data 数据
Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑🤝🧑👫🧑🏿🤝🧑🏻👩🏾🤝👨🏿👬🏿
Is there any solution? You still need to use the api service to obtain form-data data
message ImageReq {
bytes image = 1;
string image_type = 2;
}
message ImageResp {
string url = 1;
}
service File {
rpc Image(ImageReq) returns(ImageResp);
}
我能正常从 form-data 中获取到image_type数据(string类型),但是image(file类型)获取不到。