cmd/protoc-gen-go-http: fix http protoc to bind query_string (#1126)

* fix http protoc to bind query_string

Co-authored-by: longXboy <longxboyhi@gmail.com>
pull/1129/head
Tony Chen 3 years ago committed by GitHub
parent 0cdeb6c16b
commit d4d6925cd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      api/metadata/metadata.pb.go
  2. 6
      api/metadata/metadata_http.pb.go
  3. 5
      cmd/protoc-gen-go-http/http.go
  4. 13
      cmd/protoc-gen-go-http/template.go
  5. 2
      errors/errors.pb.go
  6. 4
      examples/helloworld/helloworld/helloworld_http.pb.go
  7. 2
      internal/testproto/echo_service.pb.go
  8. 18
      internal/testproto/echo_service_http.pb.go
  9. 6
      internal/testproto/echo_service_test.go
  10. 2
      internal/testproto/stream.pb.go
  11. 28
      transport/http/binding/encode.go

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.26.0 // protoc-gen-go v1.26.0
// protoc v3.15.7 // protoc v3.17.3
// source: metadata.proto // source: metadata.proto
package metadata package metadata

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go-http. DO NOT EDIT. // Code generated by protoc-gen-go-http. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go-http v2.0.0-rc5 // protoc-gen-go-http v2.0.0-rc7
package metadata 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 { func _Metadata_ListServices0_HTTP_Handler(srv MetadataHTTPServer) func(ctx http.Context) error {
return func(ctx http.Context) error { return func(ctx http.Context) error {
var in ListServicesRequest var in ListServicesRequest
if err := ctx.Bind(&in); err != nil { if err := ctx.BindQuery(&in); err != nil {
return err return err
} }
http.SetOperation(ctx, "/kratos.api.Metadata/ListServices") 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 { func _Metadata_GetServiceDesc0_HTTP_Handler(srv MetadataHTTPServer) func(ctx http.Context) error {
return func(ctx http.Context) error { return func(ctx http.Context) error {
var in GetServiceDescRequest var in GetServiceDescRequest
if err := ctx.Bind(&in); err != nil { if err := ctx.BindQuery(&in); err != nil {
return err return err
} }
if err := ctx.BindVars(&in); err != nil { if err := ctx.BindVars(&in); err != nil {

@ -104,13 +104,11 @@ func buildHTTPRule(g *protogen.GeneratedFile, m *protogen.Method, rule *annotati
method string method string
body string body string
responseBody string responseBody string
isQuery bool
) )
switch pattern := rule.Pattern.(type) { switch pattern := rule.Pattern.(type) {
case *annotations.HttpRule_Get: case *annotations.HttpRule_Get:
path = pattern.Get path = pattern.Get
method = "GET" method = "GET"
isQuery = true
case *annotations.HttpRule_Put: case *annotations.HttpRule_Put:
path = pattern.Put path = pattern.Put
method = "PUT" method = "PUT"
@ -144,7 +142,6 @@ func buildHTTPRule(g *protogen.GeneratedFile, m *protogen.Method, rule *annotati
} else if responseBody != "" { } else if responseBody != "" {
md.ResponseBody = "." + camelCaseVars(responseBody) md.ResponseBody = "." + camelCaseVars(responseBody)
} }
md.IsQuery = isQuery
return md return md
} }
@ -157,7 +154,7 @@ func buildMethodDesc(g *protogen.GeneratedFile, m *protogen.Method, method, path
Reply: g.QualifiedGoIdent(m.Output.GoIdent), Reply: g.QualifiedGoIdent(m.Output.GoIdent),
Path: path, Path: path,
Method: method, Method: method,
Vars: buildPathVars(m, path), HasVars: len(buildPathVars(m, path)) > 0,
} }
} }

@ -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 { func _{{$svrType}}_{{.Name}}{{.Num}}_HTTP_Handler(srv {{$svrType}}HTTPServer) func(ctx http.Context) error {
return func(ctx http.Context) error { return func(ctx http.Context) error {
var in {{.Request}} var in {{.Request}}
{{- if .HasBody}}
if err := ctx.Bind(&in{{.Body}}); err != nil { if err := ctx.Bind(&in{{.Body}}); err != nil {
return err 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 { if err := ctx.BindVars(&in); err != nil {
return err 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) { func (c *{{$svrType}}HTTPClientImpl) {{.Name}}(ctx context.Context, in *{{.Request}}, opts ...http.CallOption) (*{{.Reply}}, error) {
var out {{.Reply}} var out {{.Reply}}
pattern := "{{.Path}}" 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.Operation("/{{$svrName}}/{{.Name}}"))
opts = append(opts, http.PathTemplate(pattern)) opts = append(opts, http.PathTemplate(pattern))
{{if .HasBody -}} {{if .HasBody -}}
@ -94,16 +100,15 @@ type methodDesc struct {
// method // method
Name string Name string
Num int Num int
Vars []string
Request string Request string
Reply string Reply string
// http_rule // http_rule
Path string Path string
Method string Method string
HasVars bool
HasBody bool HasBody bool
Body string Body string
ResponseBody string ResponseBody string
IsQuery bool
} }
func (s *serviceDesc) execute() string { func (s *serviceDesc) execute() string {

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.26.0 // protoc-gen-go v1.26.0
// protoc v3.15.7 // protoc v3.17.3
// source: errors.proto // source: errors.proto
package errors package errors

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go-http. DO NOT EDIT. // Code generated by protoc-gen-go-http. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go-http v2.0.0-rc5 // protoc-gen-go-http v2.0.0-rc7
package helloworld 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 { func _Greeter_SayHello0_HTTP_Handler(srv GreeterHTTPServer) func(ctx http.Context) error {
return func(ctx http.Context) error { return func(ctx http.Context) error {
var in HelloRequest var in HelloRequest
if err := ctx.Bind(&in); err != nil { if err := ctx.BindQuery(&in); err != nil {
return err return err
} }
if err := ctx.BindVars(&in); err != nil { if err := ctx.BindVars(&in); err != nil {

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.26.0 // protoc-gen-go v1.26.0
// protoc v3.15.7 // protoc v3.17.3
// source: echo_service.proto // source: echo_service.proto
package testproto package testproto

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go-http. DO NOT EDIT. // Code generated by protoc-gen-go-http. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go-http v2.0.0-rc5 // protoc-gen-go-http v2.0.0-rc7
package testproto 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 { func _EchoService_Echo0_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error {
return func(ctx http.Context) error { return func(ctx http.Context) error {
var in SimpleMessage var in SimpleMessage
if err := ctx.Bind(&in); err != nil { if err := ctx.BindQuery(&in); err != nil {
return err return err
} }
if err := ctx.BindVars(&in); err != nil { 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 { func _EchoService_Echo1_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error {
return func(ctx http.Context) error { return func(ctx http.Context) error {
var in SimpleMessage var in SimpleMessage
if err := ctx.Bind(&in); err != nil { if err := ctx.BindQuery(&in); err != nil {
return err return err
} }
if err := ctx.BindVars(&in); err != nil { 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 { func _EchoService_Echo2_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error {
return func(ctx http.Context) error { return func(ctx http.Context) error {
var in SimpleMessage var in SimpleMessage
if err := ctx.Bind(&in); err != nil { if err := ctx.BindQuery(&in); err != nil {
return err return err
} }
if err := ctx.BindVars(&in); err != nil { 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 { func _EchoService_Echo3_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error {
return func(ctx http.Context) error { return func(ctx http.Context) error {
var in SimpleMessage var in SimpleMessage
if err := ctx.Bind(&in); err != nil { if err := ctx.BindQuery(&in); err != nil {
return err return err
} }
if err := ctx.BindVars(&in); err != nil { 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 { func _EchoService_Echo4_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error {
return func(ctx http.Context) error { return func(ctx http.Context) error {
var in SimpleMessage var in SimpleMessage
if err := ctx.Bind(&in); err != nil { if err := ctx.BindQuery(&in); err != nil {
return err return err
} }
if err := ctx.BindVars(&in); err != nil { 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 { func _EchoService_EchoDelete0_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error {
return func(ctx http.Context) error { return func(ctx http.Context) error {
var in SimpleMessage var in SimpleMessage
if err := ctx.Bind(&in); err != nil { if err := ctx.BindQuery(&in); err != nil {
return err return err
} }
if err := ctx.BindVars(&in); err != nil { 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) { func (c *EchoServiceHTTPClientImpl) Echo(ctx context.Context, in *SimpleMessage, opts ...http.CallOption) (*SimpleMessage, error) {
var out SimpleMessage var out SimpleMessage
pattern := "/v1/example/echo/{id}" 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.Operation("/testproto.EchoService/Echo"))
opts = append(opts, http.PathTemplate(pattern)) opts = append(opts, http.PathTemplate(pattern))
err := c.cc.Invoke(ctx, "POST", path, nil, &out, opts...) 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) { func (c *EchoServiceHTTPClientImpl) EchoDelete(ctx context.Context, in *SimpleMessage, opts ...http.CallOption) (*SimpleMessage, error) {
var out SimpleMessage var out SimpleMessage
pattern := "/v1/example/echo_delete/{id}/{num}" 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.Operation("/testproto.EchoService/EchoDelete"))
opts = append(opts, http.PathTemplate(pattern)) opts = append(opts, http.PathTemplate(pattern))
err := c.cc.Invoke(ctx, "DELETE", path, nil, &out, opts...) err := c.cc.Invoke(ctx, "DELETE", path, nil, &out, opts...)

@ -129,7 +129,9 @@ func TestEchoHTTPServer(t *testing.T) {
func testEchoHTTPClient(t *testing.T, addr string) { func testEchoHTTPClient(t *testing.T, addr string) {
var ( var (
err error 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{} out = &SimpleMessage{}
) )
check := func(name string, in, 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" { if header.Get("2233") != "niang" {
t.Errorf("[echo] header key 2233 expected niang got %v", header.Get("2233")) 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 { if out, err = cli.EchoBody(context.Background(), in); err != nil {
t.Fatal(err) t.Fatal(err)

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.26.0 // protoc-gen-go v1.26.0
// protoc v3.15.7 // protoc v3.17.3
// source: stream.proto // source: stream.proto
package testproto package testproto

@ -92,24 +92,38 @@ func getValueByField(v protoreflect.Message, fieldPath []string) (string, error)
func encodeByField(u url.Values, path string, v protoreflect.Message) error { func encodeByField(u url.Values, path string, v protoreflect.Message) error {
for i := 0; i < v.Descriptor().Fields().Len(); i++ { for i := 0; i < v.Descriptor().Fields().Len(); i++ {
fd := v.Descriptor().Fields().Get(i) fd := v.Descriptor().Fields().Get(i)
var key string = fd.TextName() var key string
var newPath string var newPath string
if fd.HasJSONName() {
key = fd.JSONName()
} else {
key = fd.TextName()
}
if path == "" { if path == "" {
newPath = key newPath = key
} else { } else {
newPath = path + "." + key 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 { switch {
case fd.IsList(): case fd.IsList():
if v.Get(fd).List().Len() > 0 {
list, err := encodeRepeatedField(fd, v.Get(fd).List()) list, err := encodeRepeatedField(fd, v.Get(fd).List())
if err != nil { if err != nil {
return err return err
} }
u[newPath] = list u[newPath] = list
}
case fd.IsMap(): case fd.IsMap():
if v.Get(fd).Map().Len() > 0 {
m, err := encodeMapField(fd, v.Get(fd).Map()) m, err := encodeMapField(fd, v.Get(fd).Map())
if err != nil { if err != nil {
return err return err
@ -117,13 +131,17 @@ func encodeByField(u url.Values, path string, v protoreflect.Message) error {
for k, value := range m { for k, value := range m {
u[fmt.Sprintf("%s[%s]", newPath, k)] = []string{value} u[fmt.Sprintf("%s[%s]", newPath, k)] = []string{value}
} }
}
case (fd.Kind() == protoreflect.MessageKind) || (fd.Kind() == protoreflect.GroupKind): case (fd.Kind() == protoreflect.MessageKind) || (fd.Kind() == protoreflect.GroupKind):
value, err := encodeMessage(fd.Message(), v.Get(fd)) value, err := encodeMessage(fd.Message(), v.Get(fd))
if err == nil { if err == nil {
u[newPath] = []string{value} 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: default:
value, err := encodeField(fd, v.Get(fd)) value, err := encodeField(fd, v.Get(fd))
if err != nil { if err != nil {

Loading…
Cancel
Save