diff --git a/runtime/query.go b/runtime/query.go index d9f3b2583c7..a71ffe13847 100644 --- a/runtime/query.go +++ b/runtime/query.go @@ -149,11 +149,13 @@ func populateRepeatedField(f reflect.Value, values []string, props *proto.Proper } func populateField(f reflect.Value, value string, props *proto.Properties) error { - // Handle well known type + i := f.Addr().Interface() + + // Handle protobuf well known types type wkt interface { XXX_WellKnownType() string } - if wkt, ok := f.Addr().Interface().(wkt); ok { + if wkt, ok := i.(wkt); ok { switch wkt.XXX_WellKnownType() { case "Timestamp": if value == "null" { @@ -218,6 +220,20 @@ func populateField(f reflect.Value, value string, props *proto.Properties) error } } + // Handle google well known types + if gwkt, ok := i.(proto.Message); ok { + switch proto.MessageName(gwkt) { + case "google.protobuf.FieldMask": + p := f.Field(0) + for _, v := range strings.Split(value, ",") { + if v != "" { + p.Set(reflect.Append(p, reflect.ValueOf(v))) + } + } + return nil + } + } + // is the destination field an enumeration type? if enumValMap := proto.EnumValueMap(props.Enum); enumValMap != nil { return populateFieldEnum(f, value, enumValMap) diff --git a/runtime/query_test.go b/runtime/query_test.go index d5b4c758469..8d5ac5f7040 100644 --- a/runtime/query_test.go +++ b/runtime/query_test.go @@ -15,6 +15,7 @@ import ( "github.com/golang/protobuf/ptypes/wrappers" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/genproto/protobuf/field_mask" ) func TestPopulateParameters(t *testing.T) { @@ -25,6 +26,9 @@ func TestPopulateParameters(t *testing.T) { t.Fatalf("Couldn't setup timestamp in Protobuf format: %v", err) } + fieldmaskStr := "float_value,double_value" + fieldmaskPb := &field_mask.FieldMask{[]string{"float_value", "double_value"}} + for _, spec := range []struct { values url.Values filter *utilities.DoubleArray @@ -46,6 +50,7 @@ func TestPopulateParameters(t *testing.T) { "enum_value": {"1"}, "repeated_enum": {"1", "2", "0"}, "timestamp_value": {timeStr}, + "fieldmask_value": {fieldmaskStr}, "wrapper_float_value": {"1.5"}, "wrapper_double_value": {"2.5"}, "wrapper_int64_value": {"-1"}, @@ -71,6 +76,7 @@ func TestPopulateParameters(t *testing.T) { EnumValue: EnumValue_Y, RepeatedEnum: []EnumValue{EnumValue_Y, EnumValue_Z, EnumValue_X}, TimestampValue: timePb, + FieldMaskValue: fieldmaskPb, WrapperFloatValue: &wrappers.FloatValue{1.5}, WrapperDoubleValue: &wrappers.DoubleValue{2.5}, WrapperInt64Value: &wrappers.Int64Value{-1}, @@ -97,6 +103,7 @@ func TestPopulateParameters(t *testing.T) { "enumValue": {"1"}, "repeatedEnum": {"1", "2", "0"}, "timestampValue": {timeStr}, + "fieldmaskValue": {fieldmaskStr}, "wrapperFloatValue": {"1.5"}, "wrapperDoubleValue": {"2.5"}, "wrapperInt64Value": {"-1"}, @@ -122,6 +129,7 @@ func TestPopulateParameters(t *testing.T) { EnumValue: EnumValue_Y, RepeatedEnum: []EnumValue{EnumValue_Y, EnumValue_Z, EnumValue_X}, TimestampValue: timePb, + FieldMaskValue: fieldmaskPb, WrapperFloatValue: &wrappers.FloatValue{1.5}, WrapperDoubleValue: &wrappers.DoubleValue{2.5}, WrapperInt64Value: &wrappers.Int64Value{-1}, @@ -484,6 +492,7 @@ type proto3Message struct { EnumValue EnumValue `protobuf:"varint,11,opt,name=enum_value,json=enumValue,enum=runtime_test_api.EnumValue" json:"enum_value,omitempty"` RepeatedEnum []EnumValue `protobuf:"varint,12,rep,packed,name=repeated_enum,json=repeatedEnum,enum=runtime_test_api.EnumValue" json:"repeated_enum,omitempty"` TimestampValue *timestamp.Timestamp `protobuf:"bytes,16,opt,name=timestamp_value,json=timestampValue" json:"timestamp_value,omitempty"` + FieldMaskValue *field_mask.FieldMask `protobuf:"bytes,27,opt,name=fieldmask_value,json=fieldmaskValue" json:"fieldmask_value,omitempty"` OneofValue proto3Message_OneofValue `protobuf_oneof:"oneof_value"` WrapperDoubleValue *wrappers.DoubleValue `protobuf:"bytes,17,opt,name=wrapper_double_value,json=wrapperDoubleValue" json:"wrapper_double_value,omitempty"` WrapperFloatValue *wrappers.FloatValue `protobuf:"bytes,18,opt,name=wrapper_float_value,json=wrapperFloatValue" json:"wrapper_float_value,omitempty"`