Skip to content

Commit

Permalink
Attach instance of AnyResolver to jsonpb.Marshaler for gRPC (uber#422)
Browse files Browse the repository at this point in the history
  • Loading branch information
bufdev authored Apr 5, 2019
1 parent d077d5a commit 487b477
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 30 deletions.
2 changes: 2 additions & 0 deletions internal/cmd/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ go_test(
"@com_github_stretchr_testify//require:go_default_library",
"@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_google_grpc//codes:go_default_library",
"@org_golang_google_grpc//credentials:go_default_library",
"@org_golang_google_grpc//status:go_default_library",
],
)
19 changes: 16 additions & 3 deletions internal/cmd/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ import (
"github.com/uber/prototool/internal/settings"
"github.com/uber/prototool/internal/vars"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/status"
)

func TestCompile(t *testing.T) {
Expand Down Expand Up @@ -1444,10 +1446,7 @@ func TestGRPC(t *testing.T) {
ssClientCrt,
"--server-name", "client.local",
)
}

func TestGRPCError(t *testing.T) {
t.Parallel()
assertGRPCExclamationError(t,
errors.New("test"),
1,
Expand All @@ -1459,6 +1458,20 @@ func TestGRPCError(t *testing.T) {
`{"value":"hello"}`,
`--details`,
)

st, err := status.New(codes.InvalidArgument, "test").WithDetails(&grpcpb.Foo{Bar: "baz"})
assert.NoError(t, err)
assertGRPCExclamationError(t,
status.ErrorProto(st.Proto()),
1,
`{"status":{"code":3,"message":"test","details":[{"@type":"type.googleapis.com/grpc.Foo","bar":"baz"}]}}
{"trailers":{"content-type":["application/grpc"]}}
rpc error: code = InvalidArgument desc = test`,
"testdata/grpc/grpc.proto",
"grpc.ExcitedService/Exclamation",
`{"value":"hello"}`,
`--details`,
)
}

func TestVersion(t *testing.T) {
Expand Down
73 changes: 57 additions & 16 deletions internal/cmd/testdata/grpc/gen/grpcpb/grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions internal/cmd/testdata/grpc/grpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ option java_multiple_files = true;
option java_outer_classname = "GrpcProto";
option java_package = "com.grpc";

message Foo {
string bar = 1;
}

message ExclamationRequest {
string value = 1;
}
Expand Down
1 change: 1 addition & 0 deletions internal/grpc/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ go_library(
"@com_github_golang_protobuf//jsonpb:go_default_library_gen",
"@com_github_golang_protobuf//proto:go_default_library",
"@com_github_jhump_protoreflect//desc:go_default_library",
"@com_github_jhump_protoreflect//dynamic:go_default_library",
"@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_google_grpc//credentials:go_default_library",
Expand Down
33 changes: 30 additions & 3 deletions internal/grpc/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import (
"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/protoc-gen-go/descriptor"
protoreflectdesc "github.com/jhump/protoreflect/desc"
"github.com/jhump/protoreflect/dynamic"
"github.com/uber/prototool/internal/desc"
"go.uber.org/zap"
"google.golang.org/grpc"
Expand Down Expand Up @@ -72,7 +74,11 @@ func newHandler(options ...HandlerOption) *handler {
}

func (h *handler) Invoke(fileDescriptorSets []*descriptor.FileDescriptorSet, address string, method string, inputReader io.Reader, outputWriter io.Writer) error {
descriptorSource, err := h.getDescriptorSourceForMethod(fileDescriptorSets, method)
descriptorSource, err := getDescriptorSourceForMethod(fileDescriptorSets, method)
if err != nil {
return err
}
anyResolver, err := getAnyResolver(fileDescriptorSets)
if err != nil {
return err
}
Expand All @@ -81,7 +87,7 @@ func (h *handler) Invoke(fileDescriptorSets []*descriptor.FileDescriptorSet, add
return err
}
defer func() { _ = clientConn.Close() }()
invocationEventHandler := newInvocationEventHandler(outputWriter, h.logger, h.details)
invocationEventHandler := newInvocationEventHandler(anyResolver, outputWriter, h.logger, h.details)
ctx, cancel := context.WithTimeout(context.Background(), h.callTimeout)
defer cancel()
if err := grpcurl.InvokeRPC(
Expand Down Expand Up @@ -157,7 +163,28 @@ func (h *handler) getDialOptions() []grpc.DialOption {
return dialOptions
}

func (h *handler) getDescriptorSourceForMethod(fileDescriptorSets []*descriptor.FileDescriptorSet, method string) (grpcurl.DescriptorSource, error) {
func getAnyResolver(fileDescriptorSets []*descriptor.FileDescriptorSet) (jsonpb.AnyResolver, error) {
var fileDescriptors []*protoreflectdesc.FileDescriptor
for _, fileDescriptorSet := range fileDescriptorSets {
for _, fileDescriptorProto := range fileDescriptorSet.File {
iFileDescriptorSet, err := desc.SortFileDescriptorSet(fileDescriptorSet, fileDescriptorProto)
if err != nil {
return nil, err
}
fileDescriptor, err := protoreflectdesc.CreateFileDescriptorFromSet(iFileDescriptorSet)
if err != nil {
return nil, err
}
fileDescriptors = append(fileDescriptors, fileDescriptor)
}
}
return dynamic.AnyResolver(
dynamic.NewMessageFactoryWithDefaults(),
fileDescriptors...,
), nil
}

func getDescriptorSourceForMethod(fileDescriptorSets []*descriptor.FileDescriptorSet, method string) (grpcurl.DescriptorSource, error) {
servicePath, err := getServiceForMethod(method)
if err != nil {
return nil, err
Expand Down
18 changes: 10 additions & 8 deletions internal/grpc/invocation_event_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,21 @@ import (
"google.golang.org/grpc/status"
)

var jsonpbMarshaler = &jsonpb.Marshaler{}

var _ grpcurl.InvocationEventHandler = &invocationEventHandler{}

type invocationEventHandler struct {
output io.Writer
logger *zap.Logger
details bool
err error
jsonpbMarshaler *jsonpb.Marshaler
output io.Writer
logger *zap.Logger
details bool
err error
}

func newInvocationEventHandler(output io.Writer, logger *zap.Logger, details bool) *invocationEventHandler {
func newInvocationEventHandler(anyResolver jsonpb.AnyResolver, output io.Writer, logger *zap.Logger, details bool) *invocationEventHandler {
return &invocationEventHandler{
jsonpbMarshaler: &jsonpb.Marshaler{
AnyResolver: anyResolver,
},
output: output,
logger: logger,
details: details,
Expand Down Expand Up @@ -90,7 +92,7 @@ func (i *invocationEventHandler) printProtoMessage(input proto.Message, detailsK
if input == nil {
return
}
s, err := jsonpbMarshaler.MarshalToString(input)
s, err := i.jsonpbMarshaler.MarshalToString(input)
if err != nil {
i.logger.Error("marshal error", zap.Error(err))
return
Expand Down

0 comments on commit 487b477

Please sign in to comment.