oneof possibilitiesmessage GetSomethingMsg {
string name = 1;
oneof credentials {
AWSCredentials aws = 2;
AzureCredentials azure = 3;
}
}
message AWSCredentials {
string secret_key_id = 1;
string secret_access_key = 2;
string region = 3;
}
message AzureCredentials {
string app_id = 1;
string tenant = 2;
string password = 3;
string subscription_id = 4;
}
rpc GetSomething (GetSomethingMsg) returns (GetSomethingReply) {
option (google.api.http) = {
get : "/api/v1/something"
};
}
rpc GetSomethingV2 (GetSomethingMsg) returns (GetSomethingReply) {
option (google.api.http) = {
post : "/api/v2/something"
body : "*"
};
}
curl "http://localhost:9050/api/v1/something?name=abc&azure.app_id=abc&azure.tenant=def&azure.password=ghi&azure.subscription_id=jkl"
{"error":"field already set for credentials oneof","message":"field already set for credentials oneof","code":3}
The POST will work just fine, as expected
Both solutions to work
I've noticed that if I only set a single value for the nested message, it does not error out. So if I do
curl "http://localhost:9050/api/v1/something?name=abc&azure.app_id=abc"
It will be happy with me - which makes me think there is some glitch in how get parameters are being parsed. The post is doing fine, so I suspect it has something to do with assembling the get values together into a single object.
I could totally be wrong too.
There are similar issues - https://github.com/grpc-ecosystem/grpc-gateway/issues/460 and https://github.com/grpc-ecosystem/grpc-gateway/issues/413 - but they seem to be different, so I figured the issue was worth filing.
This was all done using protoc 3.6.1, grpc-gateway 1.5.0, golang/protobuf 1.2.0 - at least if dep has not deceived me.
Thanks!
Thanks for raising this issue. There are a couple of known shortcomings with the translation from query parameters to proto request messages, as you noticed. I don't think anyone is working on a fix for this right now and the recommendation is usually to use a POST where you need this kind of information.
Of course, we'll be happy to help you get a PR in that would resolve this issue. You've got a good test case here, so you might be able to fix this :). What do you say?
@johanbrandhorst @venezia I would like to work on this if that is fine :)
@waveywaves of course! Thanks!
I have started work on this. Please assign it to me.
Doesn't seem like I can assign it to you, but consider yourself the owner.
@johanbrandhorst this still not fixed,right?
I can take a look at this later this weekend perhaps - thought someone was doing this - sorry
Feel free @venezia, don't think @waveywaves got anywhere yet.
@johanbrandhorst I want to know is there anyone helping this?when will this could be done? thanks
@lzxm160 it sounds like there is no one working on it. I think this would be a great starter project to learn the inner workings of the project. Feel free to comment here if you need any pointers on where to start.
Hi, I'd like to work on this if possible.
Ok, go ahead, I don't think anyone is working on it.
Can you point to where I need to go to get started on this?
@johanbrandhorst
It would probably be somewhere in https://github.com/grpc-ecosystem/grpc-gateway/blob/master/runtime/query.go. The easiest thing might be to create a failing test and add it to https://github.com/grpc-ecosystem/grpc-gateway/blob/master/runtime/query_test.go first.
I'll be working on this over the next few days/weeks.
Hello, any update on this?
@hkarimi1985 not yet
Hello, any update on this?
Doesn't look like it, if you've got the time to look into this, please feel free. It doesn't seem like @chimeworld found the time for it yet.
This issue seems to also apply for additional_bindings, when using something like the following:
import "google/api/annotations.proto";
service FooBarAPI {
rpc FooBar(FooBarRequest) returns (FooBarResponse) {
option (google.api.http) = {
post: "/foo/bar/account/{account_id}"
body: "*"
additional_bindings: {
post: "/foo/bar/iban/{email_iban.iban}/email/{email_iban.email}"
body: "*"
}
};
}
}
message FooBarRequest {
// The account you are requesting.
oneof account {
// The UUID of the account.
string account_id = 1;
// The email + IBAN as a message.
EmailIBAN email_iban = 2;
}
// Message that contains email and IBAN, useful when selecting an account.
message EmailIBAN {
// The IBAN of the account.
string iban = 1;
// The email of the account.
string email = 2;
}
}
message FooBarResponse {
bool success = 1;
}
This generates the following code:
var (
val string
e int32
ok bool
err error
_ = err
)
val, ok = pathParams["email_iban.iban"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "email_iban.iban")
}
err = runtime.PopulateFieldFromPath(&protoReq, "email_iban.iban", val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "email_iban.iban", err)
}
val, ok = pathParams["email_iban.email"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "email_iban.email")
}
err = runtime.PopulateFieldFromPath(&protoReq, "email_iban.email", val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "email_iban.email", err)
}
And throws the error type mismatch, parameter: email_iban.email, error: field already set for account oneof when it tries to set email_iban.email.
EDIT: I was still using v1.15.0. It works on v2.0.1.
Most helpful comment
I have started work on this. Please assign it to me.