github.com/jhump/protoreflect@v1.16.0/grpcreflect/server.go (about) 1 package grpcreflect 2 3 import ( 4 "fmt" 5 6 "google.golang.org/grpc" 7 "google.golang.org/grpc/reflection" 8 9 "github.com/jhump/protoreflect/desc" 10 ) 11 12 // GRPCServer is the interface provided by a gRPC server. In addition to being a 13 // service registrar (for registering services and handlers), it also has an 14 // accessor for retrieving metadata about all registered services. 15 type GRPCServer = reflection.GRPCServer 16 17 // LoadServiceDescriptors loads the service descriptors for all services exposed by the 18 // given GRPC server. 19 func LoadServiceDescriptors(s GRPCServer) (map[string]*desc.ServiceDescriptor, error) { 20 descs := map[string]*desc.ServiceDescriptor{} 21 for name, info := range s.GetServiceInfo() { 22 file, ok := info.Metadata.(string) 23 if !ok { 24 return nil, fmt.Errorf("service %q has unexpected metadata: expecting a string; got %v", name, info.Metadata) 25 } 26 fd, err := desc.LoadFileDescriptor(file) 27 if err != nil { 28 return nil, err 29 } 30 d := fd.FindSymbol(name) 31 if d == nil { 32 return nil, fmt.Errorf("file descriptor for %q has no element named %q", file, name) 33 } 34 sd, ok := d.(*desc.ServiceDescriptor) 35 if !ok { 36 return nil, fmt.Errorf("file descriptor for %q has incorrect element named %q: expecting a service descriptor; got %v", file, name, d) 37 } 38 descs[name] = sd 39 } 40 return descs, nil 41 } 42 43 // LoadServiceDescriptor loads a rich descriptor for a given service description 44 // generated by protoc-gen-go. Generated code contains an unexported symbol with 45 // a name like "_<Service>_serviceDesc" which is the service's description. It 46 // is used internally to register a service implementation with a GRPC server. 47 // But it can also be used by this package to retrieve the rich descriptor for 48 // the service. 49 func LoadServiceDescriptor(svc *grpc.ServiceDesc) (*desc.ServiceDescriptor, error) { 50 file, ok := svc.Metadata.(string) 51 if !ok { 52 return nil, fmt.Errorf("service %q has unexpected metadata: expecting a string; got %v", svc.ServiceName, svc.Metadata) 53 } 54 fd, err := desc.LoadFileDescriptor(file) 55 if err != nil { 56 return nil, err 57 } 58 d := fd.FindSymbol(svc.ServiceName) 59 if d == nil { 60 return nil, fmt.Errorf("file descriptor for %q has no element named %q", file, svc.ServiceName) 61 } 62 sd, ok := d.(*desc.ServiceDescriptor) 63 if !ok { 64 return nil, fmt.Errorf("file descriptor for %q has incorrect element named %q: expecting a service descriptor; got %v", file, svc.ServiceName, d) 65 } 66 return sd, nil 67 }