diff --git a/reflection/serverreflection.go b/reflection/serverreflection.go index b044a3a8f19a..c3e63574e18d 100644 --- a/reflection/serverreflection.go +++ b/reflection/serverreflection.go @@ -214,7 +214,7 @@ func (s *serverReflectionServer) serviceMetadataForSymbol(name string) (interfac return nil, fmt.Errorf("unknown symbol: %v", name) } - // Search for method in info. + // Search for method in info.Methods. var found bool for _, m := range info.Methods { if m == name[pos+1:] { @@ -222,11 +222,22 @@ func (s *serverReflectionServer) serviceMetadataForSymbol(name string) (interfac break } } - if !found { - return nil, fmt.Errorf("unknown symbol: %v", name) + if found { + return info.Metadata, nil + } + + // Search for stream in info.Streams. + for _, m := range info.Streams { + if m == name[pos+1:] { + found = true + break + } + } + if found { + return info.Metadata, nil } - return info.Metadata, nil + return nil, fmt.Errorf("unknown symbol: %v", name) } // fileDescEncodingContainingSymbol finds the file descriptor containing the given symbol, diff --git a/reflection/serverreflection_test.go b/reflection/serverreflection_test.go index aeb31e14bc26..ca9610e263ed 100644 --- a/reflection/serverreflection_test.go +++ b/reflection/serverreflection_test.go @@ -273,6 +273,7 @@ func testFileContainingSymbol(t *testing.T, stream rpb.ServerReflection_ServerRe }{ {"grpc.testing.SearchService", fdTestByte}, {"grpc.testing.SearchService.Search", fdTestByte}, + {"grpc.testing.SearchService.StreamingSearch", fdTestByte}, {"grpc.testing.SearchResponse", fdTestByte}, {"grpc.testing.ToBeExtened", fdProto2Byte}, } { diff --git a/server.go b/server.go index 7dabfc64ee31..413c019c70e4 100644 --- a/server.go +++ b/server.go @@ -245,10 +245,12 @@ func (s *Server) register(sd *ServiceDesc, ss interface{}) { s.m[sd.ServiceName] = srv } -// ServiceInfo contains method names and metadata for a service. +// ServiceInfo contains unary rpc names, streaming rpc names and metadata for a service. type ServiceInfo struct { - // Methods are method names only, without the service name or package name. + // Methods are unary rpc names only, without the service name or package name. Methods []string + // Streams are streaming rpc names only, without the service name or package name. + Streams []string // Metadata is the metadata specified in ServiceDesc when registering service. Metadata interface{} } @@ -258,16 +260,18 @@ type ServiceInfo struct { func (s *Server) GetServiceInfo() map[string]*ServiceInfo { ret := make(map[string]*ServiceInfo) for n, srv := range s.m { - methods := make([]string, 0, len(srv.md)+len(srv.sd)) + methods := make([]string, 0, len(srv.md)) for m := range srv.md { methods = append(methods, m) } - for m := range srv.sd { - methods = append(methods, m) + streams := make([]string, 0, len(srv.sd)) + for s := range srv.sd { + streams = append(streams, s) } ret[n] = &ServiceInfo{ Methods: methods, + Streams: streams, Metadata: srv.mdata, } } diff --git a/server_test.go b/server_test.go index 7c1e54dddf15..d7bf2f98f5d8 100644 --- a/server_test.go +++ b/server_test.go @@ -94,6 +94,8 @@ func TestGetServiceInfo(t *testing.T) { "grpc.testing.EmptyService": &ServiceInfo{ Methods: []string{ "EmptyCall", + }, + Streams: []string{ "EmptyStream", }, Metadata: []int{0, 2, 1, 3},