diff --git a/encoding/form/proto_encode.go b/encoding/form/proto_encode.go index 550648dcf..354bfa7c2 100644 --- a/encoding/form/proto_encode.go +++ b/encoding/form/proto_encode.go @@ -20,7 +20,7 @@ func EncodeValues(msg interface{}) (url.Values, error) { } if v, ok := msg.(proto.Message); ok { u := make(url.Values) - err := encodeByField(u, "", v.ProtoReflect()) + err := encodeByField(u, "", v.ProtoReflect(), false) if err != nil { return nil, err } @@ -29,13 +29,31 @@ func EncodeValues(msg interface{}) (url.Values, error) { return encoder.Encode(msg) } -func encodeByField(u url.Values, path string, m protoreflect.Message) (finalErr error) { +// EncodeTextNameValues encode a message into url values. +func EncodeTextNameValues(msg interface{}) (url.Values, error) { + if msg == nil || (reflect.ValueOf(msg).Kind() == reflect.Ptr && reflect.ValueOf(msg).IsNil()) { + return url.Values{}, nil + } + if v, ok := msg.(proto.Message); ok { + u := make(url.Values) + err := encodeByField(u, "", v.ProtoReflect(), true) + if err != nil { + return nil, err + } + return u, nil + } + return encoder.Encode(msg) +} + +func encodeByField(u url.Values, path string, m protoreflect.Message, forceTextName bool) (finalErr error) { m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { var ( key string newPath string ) - if fd.HasJSONName() { + if forceTextName { + key = fd.TextName() + } else if fd.HasJSONName() { key = fd.JSONName() } else { key = fd.TextName() @@ -79,7 +97,7 @@ func encodeByField(u url.Values, path string, m protoreflect.Message) (finalErr u.Set(newPath, value) return true } - if err = encodeByField(u, newPath, v.Message()); err != nil { + if err = encodeByField(u, newPath, v.Message(), forceTextName); err != nil { finalErr = err return false } diff --git a/transport/http/binding/encode.go b/transport/http/binding/encode.go index 5f12cf370..047d12ec7 100644 --- a/transport/http/binding/encode.go +++ b/transport/http/binding/encode.go @@ -17,6 +17,7 @@ func EncodeURL(pathTemplate string, msg interface{}, needQuery bool) string { return pathTemplate } queryParams, _ := form.EncodeValues(msg) + textNameQueryParams, _ := form.EncodeTextNameValues(msg) pathParams := make(map[string]struct{}) path := reg.ReplaceAllStringFunc(pathTemplate, func(in string) string { // it's unreachable because the reg means that must have more than one char in {} @@ -25,7 +26,11 @@ func EncodeURL(pathTemplate string, msg interface{}, needQuery bool) string { // } key := in[1 : len(in)-1] pathParams[key] = struct{}{} - return queryParams.Get(key) + value := queryParams.Get(key) + if len(value) > 0 { + return value + } + return textNameQueryParams.Get(key) }) if !needQuery { if v, ok := msg.(proto.Message); ok {