diff --git a/internal/descriptor/services.go b/internal/descriptor/services.go index cf7ba78c5ae..4679aed2218 100644 --- a/internal/descriptor/services.go +++ b/internal/descriptor/services.go @@ -248,7 +248,7 @@ func (r *Registry) newParam(meth *Method, path string) (Parameter, error) { if IsWellKnownType(*target.TypeName) { glog.V(2).Infoln("found well known aggregate type:", target) } else { - return Parameter{}, fmt.Errorf("aggregate type %s in parameter of %s.%s: %s", target.Type, meth.Service.GetName(), meth.GetName(), path) + return Parameter{}, fmt.Errorf("%s.%s: %s is a protobuf message type. Protobuf message types cannot be used as path parameters, use a scalar value type (such as string) instead", meth.Service.GetName(), meth.GetName(), path) } } return Parameter{ diff --git a/internal/descriptor/services_test.go b/internal/descriptor/services_test.go index 6214fcc9c5f..cb9768c049a 100644 --- a/internal/descriptor/services_test.go +++ b/internal/descriptor/services_test.go @@ -1347,3 +1347,52 @@ func TestExtractServicesWithDeleteBody(t *testing.T) { t.Log(err) } } + +func TestCauseErrorWithPathParam(t *testing.T) { + src := ` + name: "path/to/example.proto", + package: "example" + message_type < + name: "TypeMessage" + field < + name: "message" + type: TYPE_MESSAGE + type_name: 'ExampleMessage' + number: 1, + label: LABEL_OPTIONAL + > + > + service < + name: "ExampleService" + method < + name: "Echo" + input_type: "TypeMessage" + output_type: "TypeMessage" + options < + [google.api.http] < + get: "/v1/example/echo/{message=*}" + > + > + > + > + ` + var fd descriptorpb.FileDescriptorProto + if err := prototext.Unmarshal([]byte(src), &fd); err != nil { + t.Fatalf("proto.UnmarshalText(%s, &fd) failed with %v; want success", src, err) + } + target := "path/to/example.proto" + reg := NewRegistry() + input := []*descriptorpb.FileDescriptorProto{&fd} + reg.loadFile(fd.GetName(), &protogen.File{ + Proto: &fd, + }) + // switch this field to see the error + wantErr := true + err := reg.loadServices(reg.files[target]) + if got, want := err != nil, wantErr; got != want { + if want { + t.Errorf("loadServices(%q, %q) succeeded; want an error", target, input) + } + t.Errorf("loadServices(%q, %q) failed with %v; want success", target, input, err) + } +}