Repository: go-kratos/kratos
Pull request #1126 (2021-06-29 17:44:47)

cmd/protoc-gen-go-http: fix http protoc to bind query_string
server:
body: '*' --> ResponseEncoder
body: 'field_name' --> EesponseEncoder
body: '' --> BindQuery
vars: --> BindVars

client:
body: '*' --> RequestEncoder
body: 'xxx' --> RequestEncoder
body: '' --> ?id=xxx
vars: --> /{xx}/


Patch:
diff --git a/api/metadata/metadata.pb.go b/api/metadata/metadata.pb.go
index 3f8d3bcd..ce9b0157 100644
--- a/api/metadata/metadata.pb.go
+++ b/api/metadata/metadata.pb.go
@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
 // 	protoc-gen-go v1.26.0
-// 	protoc        v3.15.7
+// 	protoc        v3.17.3
 // source: metadata.proto
 
 package metadata
diff --git a/api/metadata/metadata_http.pb.go b/api/metadata/metadata_http.pb.go
index f30262c4..4c9c3eb7 100644
--- a/api/metadata/metadata_http.pb.go
+++ b/api/metadata/metadata_http.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go-http. DO NOT EDIT.
 // versions:
-// protoc-gen-go-http v2.0.0-rc5
+// protoc-gen-go-http v2.0.0-rc7
 
 package metadata
 
@@ -31,7 +31,7 @@ func RegisterMetadataHTTPServer(s *http.Server, srv MetadataHTTPServer) {
 func _Metadata_ListServices0_HTTP_Handler(srv MetadataHTTPServer) func(ctx http.Context) error {
 	return func(ctx http.Context) error {
 		var in ListServicesRequest
-		if err := ctx.Bind(&in); err != nil {
+		if err := ctx.BindQuery(&in); err != nil {
 			return err
 		}
 		http.SetOperation(ctx, "/kratos.api.Metadata/ListServices")
@@ -50,7 +50,7 @@ func _Metadata_ListServices0_HTTP_Handler(srv MetadataHTTPServer) func(ctx http.
 func _Metadata_GetServiceDesc0_HTTP_Handler(srv MetadataHTTPServer) func(ctx http.Context) error {
 	return func(ctx http.Context) error {
 		var in GetServiceDescRequest
-		if err := ctx.Bind(&in); err != nil {
+		if err := ctx.BindQuery(&in); err != nil {
 			return err
 		}
 		if err := ctx.BindVars(&in); err != nil {
diff --git a/cmd/protoc-gen-go-http/http.go b/cmd/protoc-gen-go-http/http.go
index 9116f706..af650839 100644
--- a/cmd/protoc-gen-go-http/http.go
+++ b/cmd/protoc-gen-go-http/http.go
@@ -104,13 +104,11 @@ func buildHTTPRule(g *protogen.GeneratedFile, m *protogen.Method, rule *annotati
 		method       string
 		body         string
 		responseBody string
-		isQuery      bool
 	)
 	switch pattern := rule.Pattern.(type) {
 	case *annotations.HttpRule_Get:
 		path = pattern.Get
 		method = "GET"
-		isQuery = true
 	case *annotations.HttpRule_Put:
 		path = pattern.Put
 		method = "PUT"
@@ -144,7 +142,6 @@ func buildHTTPRule(g *protogen.GeneratedFile, m *protogen.Method, rule *annotati
 	} else if responseBody != "" {
 		md.ResponseBody = "." + camelCaseVars(responseBody)
 	}
-	md.IsQuery = isQuery
 	return md
 }
 
@@ -157,7 +154,7 @@ func buildMethodDesc(g *protogen.GeneratedFile, m *protogen.Method, method, path
 		Reply:   g.QualifiedGoIdent(m.Output.GoIdent),
 		Path:    path,
 		Method:  method,
-		Vars:    buildPathVars(m, path),
+		HasVars: len(buildPathVars(m, path)) > 0,
 	}
 }
 
diff --git a/cmd/protoc-gen-go-http/template.go b/cmd/protoc-gen-go-http/template.go
index 7bfd85f6..32fae69a 100644
--- a/cmd/protoc-gen-go-http/template.go
+++ b/cmd/protoc-gen-go-http/template.go
@@ -26,10 +26,16 @@ func Register{{.ServiceType}}HTTPServer(s *http.Server, srv {{.ServiceType}}HTTP
 func _{{$svrType}}_{{.Name}}{{.Num}}_HTTP_Handler(srv {{$svrType}}HTTPServer) func(ctx http.Context) error {
 	return func(ctx http.Context) error {
 		var in {{.Request}}
+		{{- if .HasBody}}
 		if err := ctx.Bind(&in{{.Body}}); err != nil {
 			return err
 		}
-		{{- if ne (len .Vars) 0}}
+		{{- else}}
+		if err := ctx.BindQuery(&in{{.Body}}); err != nil {
+			return err
+		}
+		{{- end}}
+		{{- if .HasVars}}
 		if err := ctx.BindVars(&in); err != nil {
 			return err
 		}
@@ -66,7 +72,7 @@ func New{{.ServiceType}}HTTPClient (client *http.Client) {{.ServiceType}}HTTPCli
 func (c *{{$svrType}}HTTPClientImpl) {{.Name}}(ctx context.Context, in *{{.Request}}, opts ...http.CallOption) (*{{.Reply}}, error) {
 	var out {{.Reply}}
 	pattern := "{{.Path}}"
-	path := binding.EncodeURL(pattern, in, {{.IsQuery}})
+	path := binding.EncodeURL(pattern, in, {{not .HasBody}})
 	opts = append(opts, http.Operation("/{{$svrName}}/{{.Name}}"))
 	opts = append(opts, http.PathTemplate(pattern))
 	{{if .HasBody -}}
@@ -94,16 +100,15 @@ type methodDesc struct {
 	// method
 	Name    string
 	Num     int
-	Vars    []string
 	Request string
 	Reply   string
 	// http_rule
 	Path         string
 	Method       string
+	HasVars      bool
 	HasBody      bool
 	Body         string
 	ResponseBody string
-	IsQuery      bool
 }
 
 func (s *serviceDesc) execute() string {
diff --git a/encoding/yaml/yaml.go b/encoding/yaml/yaml.go
index 8d8af344..b2f885f0 100644
--- a/encoding/yaml/yaml.go
+++ b/encoding/yaml/yaml.go
@@ -5,14 +5,14 @@ import (
 	"gopkg.in/yaml.v3"
 )
 
-// Name is the name registered for the json codec.
+// Name is the name registered for the yaml codec.
 const Name = "yaml"
 
 func init() {
 	encoding.RegisterCodec(codec{})
 }
 
-// codec is a Codec implementation with json.
+// codec is a Codec implementation with yaml.
 type codec struct{}
 
 func (codec) Marshal(v interface{}) ([]byte, error) {
diff --git a/errors/errors.pb.go b/errors/errors.pb.go
index 16eb19d6..ab9f3147 100644
--- a/errors/errors.pb.go
+++ b/errors/errors.pb.go
@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
 // 	protoc-gen-go v1.26.0
-// 	protoc        v3.15.7
+// 	protoc        v3.17.3
 // source: errors.proto
 
 package errors
diff --git a/examples/helloworld/helloworld/helloworld_http.pb.go b/examples/helloworld/helloworld/helloworld_http.pb.go
index 81f78683..d362a4c7 100644
--- a/examples/helloworld/helloworld/helloworld_http.pb.go
+++ b/examples/helloworld/helloworld/helloworld_http.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go-http. DO NOT EDIT.
 // versions:
-// protoc-gen-go-http v2.0.0-rc5
+// protoc-gen-go-http v2.0.0-rc7
 
 package helloworld
 
@@ -29,7 +29,7 @@ func RegisterGreeterHTTPServer(s *http.Server, srv GreeterHTTPServer) {
 func _Greeter_SayHello0_HTTP_Handler(srv GreeterHTTPServer) func(ctx http.Context) error {
 	return func(ctx http.Context) error {
 		var in HelloRequest
-		if err := ctx.Bind(&in); err != nil {
+		if err := ctx.BindQuery(&in); err != nil {
 			return err
 		}
 		if err := ctx.BindVars(&in); err != nil {
diff --git a/transport/http/binding/encode.go b/transport/http/binding/encode.go
index bc16e65e..a4b976e8 100644
--- a/transport/http/binding/encode.go
+++ b/transport/http/binding/encode.go
@@ -92,38 +92,56 @@ func getValueByField(v protoreflect.Message, fieldPath []string) (string, error)
 func encodeByField(u url.Values, path string, v protoreflect.Message) error {
 	for i := 0; i < v.Descriptor().Fields().Len(); i++ {
 		fd := v.Descriptor().Fields().Get(i)
-		var key string = fd.TextName()
+		var key string
 		var newPath string
+		if fd.HasJSONName() {
+			key = fd.JSONName()
+		} else {
+			key = fd.TextName()
+		}
 		if path == "" {
 			newPath = key
 		} else {
 			newPath = path + "." + key
 		}
-		if fd.HasJSONName() {
-			key = fd.JSONName()
+
+		if of := fd.ContainingOneof(); of != nil {
+			if f := v.WhichOneof(of); f != nil {
+				if f != fd {
+					continue
+				}
+			}
+			continue
 		}
 		switch {
 		case fd.IsList():
-			list, err := encodeRepeatedField(fd, v.Get(fd).List())
-			if err != nil {
-				return err
+			if v.Get(fd).List().Len() > 0 {
+				list, err := encodeRepeatedField(fd, v.Get(fd).List())
+				if err != nil {
+					return err
+				}
+				u[newPath] = list
 			}
-			u[newPath] = list
 		case fd.IsMap():
-			m, err := encodeMapField(fd, v.Get(fd).Map())
-			if err != nil {
-				return err
-			}
-			for k, value := range m {
-				u[fmt.Sprintf("%s[%s]", newPath, k)] = []string{value}
+			if v.Get(fd).Map().Len() > 0 {
+				m, err := encodeMapField(fd, v.Get(fd).Map())
+				if err != nil {
+					return err
+				}
+				for k, value := range m {
+					u[fmt.Sprintf("%s[%s]", newPath, k)] = []string{value}
+				}
 			}
 		case (fd.Kind() == protoreflect.MessageKind) || (fd.Kind() == protoreflect.GroupKind):
 			value, err := encodeMessage(fd.Message(), v.Get(fd))
 			if err == nil {
 				u[newPath] = []string{value}
-				return nil
+				continue
+			}
+			err = encodeByField(u, newPath, v.Get(fd).Message())
+			if err != nil {
+				return err
 			}
-			return encodeByField(u, newPath, v.Get(fd).Message())
 		default:
 			value, err := encodeField(fd, v.Get(fd))
 			if err != nil {


Test patch:
diff --git a/internal/testproto/echo_service.pb.go b/internal/testproto/echo_service.pb.go
index 5ff2d3c8..0ffaac82 100644
--- a/internal/testproto/echo_service.pb.go
+++ b/internal/testproto/echo_service.pb.go
@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
 // 	protoc-gen-go v1.26.0
-// 	protoc        v3.15.7
+// 	protoc        v3.17.3
 // source: echo_service.proto
 
 package testproto
diff --git a/internal/testproto/echo_service_http.pb.go b/internal/testproto/echo_service_http.pb.go
index c12452fd..7500dbfb 100644
--- a/internal/testproto/echo_service_http.pb.go
+++ b/internal/testproto/echo_service_http.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go-http. DO NOT EDIT.
 // versions:
-// protoc-gen-go-http v2.0.0-rc5
+// protoc-gen-go-http v2.0.0-rc7
 
 package testproto
 
@@ -41,7 +41,7 @@ func RegisterEchoServiceHTTPServer(s *http.Server, srv EchoServiceHTTPServer) {
 func _EchoService_Echo0_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error {
 	return func(ctx http.Context) error {
 		var in SimpleMessage
-		if err := ctx.Bind(&in); err != nil {
+		if err := ctx.BindQuery(&in); err != nil {
 			return err
 		}
 		if err := ctx.BindVars(&in); err != nil {
@@ -63,7 +63,7 @@ func _EchoService_Echo0_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Co
 func _EchoService_Echo1_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error {
 	return func(ctx http.Context) error {
 		var in SimpleMessage
-		if err := ctx.Bind(&in); err != nil {
+		if err := ctx.BindQuery(&in); err != nil {
 			return err
 		}
 		if err := ctx.BindVars(&in); err != nil {
@@ -85,7 +85,7 @@ func _EchoService_Echo1_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Co
 func _EchoService_Echo2_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error {
 	return func(ctx http.Context) error {
 		var in SimpleMessage
-		if err := ctx.Bind(&in); err != nil {
+		if err := ctx.BindQuery(&in); err != nil {
 			return err
 		}
 		if err := ctx.BindVars(&in); err != nil {
@@ -107,7 +107,7 @@ func _EchoService_Echo2_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Co
 func _EchoService_Echo3_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error {
 	return func(ctx http.Context) error {
 		var in SimpleMessage
-		if err := ctx.Bind(&in); err != nil {
+		if err := ctx.BindQuery(&in); err != nil {
 			return err
 		}
 		if err := ctx.BindVars(&in); err != nil {
@@ -129,7 +129,7 @@ func _EchoService_Echo3_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Co
 func _EchoService_Echo4_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error {
 	return func(ctx http.Context) error {
 		var in SimpleMessage
-		if err := ctx.Bind(&in); err != nil {
+		if err := ctx.BindQuery(&in); err != nil {
 			return err
 		}
 		if err := ctx.BindVars(&in); err != nil {
@@ -189,7 +189,7 @@ func _EchoService_EchoResponseBody0_HTTP_Handler(srv EchoServiceHTTPServer) func
 func _EchoService_EchoDelete0_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error {
 	return func(ctx http.Context) error {
 		var in SimpleMessage
-		if err := ctx.Bind(&in); err != nil {
+		if err := ctx.BindQuery(&in); err != nil {
 			return err
 		}
 		if err := ctx.BindVars(&in); err != nil {
@@ -246,7 +246,7 @@ func NewEchoServiceHTTPClient(client *http.Client) EchoServiceHTTPClient {
 func (c *EchoServiceHTTPClientImpl) Echo(ctx context.Context, in *SimpleMessage, opts ...http.CallOption) (*SimpleMessage, error) {
 	var out SimpleMessage
 	pattern := "/v1/example/echo/{id}"
-	path := binding.EncodeURL(pattern, in, false)
+	path := binding.EncodeURL(pattern, in, true)
 	opts = append(opts, http.Operation("/testproto.EchoService/Echo"))
 	opts = append(opts, http.PathTemplate(pattern))
 	err := c.cc.Invoke(ctx, "POST", path, nil, &out, opts...)
@@ -272,7 +272,7 @@ func (c *EchoServiceHTTPClientImpl) EchoBody(ctx context.Context, in *SimpleMess
 func (c *EchoServiceHTTPClientImpl) EchoDelete(ctx context.Context, in *SimpleMessage, opts ...http.CallOption) (*SimpleMessage, error) {
 	var out SimpleMessage
 	pattern := "/v1/example/echo_delete/{id}/{num}"
-	path := binding.EncodeURL(pattern, in, false)
+	path := binding.EncodeURL(pattern, in, true)
 	opts = append(opts, http.Operation("/testproto.EchoService/EchoDelete"))
 	opts = append(opts, http.PathTemplate(pattern))
 	err := c.cc.Invoke(ctx, "DELETE", path, nil, &out, opts...)
diff --git a/internal/testproto/echo_service_test.go b/internal/testproto/echo_service_test.go
index 5704be63..d6f71f4e 100644
--- a/internal/testproto/echo_service_test.go
+++ b/internal/testproto/echo_service_test.go
@@ -129,7 +129,9 @@ func TestEchoHTTPServer(t *testing.T) {
 func testEchoHTTPClient(t *testing.T, addr string) {
 	var (
 		err error
-		in  = &SimpleMessage{Id: "test_id", Num: 100}
+		in  = &SimpleMessage{Id: "test_id", Num: 100, Ext: &SimpleMessage_No{
+			No: &Embedded{Mark: &Embedded_Note{Note: "2233"}},
+		}}
 		out = &SimpleMessage{}
 	)
 	check := func(name string, in, out *SimpleMessage) {
@@ -153,7 +155,7 @@ func testEchoHTTPClient(t *testing.T, addr string) {
 	if header.Get("2233") != "niang" {
 		t.Errorf("[echo] header key 2233 expected niang got %v", header.Get("2233"))
 	}
-	check("echo", &SimpleMessage{Id: "test_id"}, out)
+	check("echo", &SimpleMessage{Id: "test_id", Num: 100, Ext: &SimpleMessage_No{No: &Embedded{Mark: &Embedded_Note{Note: "2233"}}}}, out)
 
 	if out, err = cli.EchoBody(context.Background(), in); err != nil {
 		t.Fatal(err)
diff --git a/internal/testproto/stream.pb.go b/internal/testproto/stream.pb.go
index 7036cf0b..d2fb0bbb 100644
--- a/internal/testproto/stream.pb.go
+++ b/internal/testproto/stream.pb.go
@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
 // 	protoc-gen-go v1.26.0
-// 	protoc        v3.15.7
+// 	protoc        v3.17.3
 // source: stream.proto
 
 package testproto