From 583755b3cb3cd3d2f4aa9718473b099cce16d8ee Mon Sep 17 00:00:00 2001 From: Michal Witkowski Date: Mon, 27 Jul 2015 23:36:12 +0100 Subject: [PATCH] Fix bug with nested proto3 messages in URL parameters, by reusing the reflection code. --- protoc-gen-grpc-gateway/descriptor/types.go | 8 ++++++++ protoc-gen-grpc-gateway/gengateway/template.go | 4 ++++ runtime/query.go | 11 +++++++++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/protoc-gen-grpc-gateway/descriptor/types.go b/protoc-gen-grpc-gateway/descriptor/types.go index 089aca06c42..e9fb6e1b9d3 100644 --- a/protoc-gen-grpc-gateway/descriptor/types.go +++ b/protoc-gen-grpc-gateway/descriptor/types.go @@ -196,6 +196,14 @@ func (p FieldPath) String() string { return strings.Join(components, ".") } +// IsNestedProto3 indicates whether the FieldPath is a nested Proto3 path. +func (p FieldPath) IsNestedProto3() bool { + if len(p) > 1 && !p[0].Target.Message.File.proto2() { + return true + } + return false +} + // RHS is a right-hand-side expression in go to be used to assign a value to the target field. // It starts with "msgExpr", which is the go expression of the method request object. func (p FieldPath) RHS(msgExpr string) string { diff --git a/protoc-gen-grpc-gateway/gengateway/template.go b/protoc-gen-grpc-gateway/gengateway/template.go index 9947d8de556..c005bafef91 100644 --- a/protoc-gen-grpc-gateway/gengateway/template.go +++ b/protoc-gen-grpc-gateway/gengateway/template.go @@ -188,7 +188,11 @@ var ( if !ok { return nil, grpc.Errorf(codes.InvalidArgument, "missing parameter %s", {{$param | printf "%q"}}) } +{{if $param.IsNestedProto3 }} + err = runtime.PopulateFieldFromPath(&protoReq, {{$param | printf "%q"}}, val) +{{else}} {{$param.RHS "protoReq"}}, err = {{$param.ConvertFuncExpr}}(val) +{{end}} if err != nil { return nil, err } diff --git a/runtime/query.go b/runtime/query.go index 63ce09278aa..67448cb7096 100644 --- a/runtime/query.go +++ b/runtime/query.go @@ -19,14 +19,21 @@ func PopulateQueryParameters(msg proto.Message, values url.Values, filter *inter if filter.HasCommonPrefix(fieldPath) { continue } - if err := populateQueryParameter(msg, fieldPath, values); err != nil { + if err := populateFieldValueFromPath(msg, fieldPath, values); err != nil { return err } } return nil } -func populateQueryParameter(msg proto.Message, fieldPath []string, values []string) error { +// PopulateFieldFromPath sets a value in a nested Protobuf structure. +// It instantiates missing protobuf fields as it goes. +func PopulateFieldFromPath(msg proto.Message, fieldPathString string, value string) error { + fieldPath := strings.Split(fieldPathString, ".") + return populateFieldValueFromPath(msg, fieldPath, []string{value}) +} + +func populateFieldValueFromPath(msg proto.Message, fieldPath []string, values []string) error { m := reflect.ValueOf(msg) if m.Kind() != reflect.Ptr { return fmt.Errorf("unexpected type %T: %v", msg, msg)