blob: c9ef6192ee5399d6cf9a13145238c95c43b697f6 [file] [log] [blame]
package grpcreflect
import (
"fmt"
"google.golang.org/grpc"
"github.com/jhump/protoreflect/desc"
)
// LoadServiceDescriptors loads the service descriptors for all services exposed by the
// given GRPC server.
func LoadServiceDescriptors(s *grpc.Server) (map[string]*desc.ServiceDescriptor, error) {
descs := map[string]*desc.ServiceDescriptor{}
for name, info := range s.GetServiceInfo() {
file, ok := info.Metadata.(string)
if !ok {
return nil, fmt.Errorf("service %q has unexpected metadata: expecting a string; got %v", name, info.Metadata)
}
fd, err := desc.LoadFileDescriptor(file)
if err != nil {
return nil, err
}
d := fd.FindSymbol(name)
if d == nil {
return nil, fmt.Errorf("file descriptor for %q has no element named %q", file, name)
}
sd, ok := d.(*desc.ServiceDescriptor)
if !ok {
return nil, fmt.Errorf("file descriptor for %q has incorrect element named %q: expecting a service descriptor; got %v", file, name, d)
}
descs[name] = sd
}
return descs, nil
}
// LoadServiceDescriptor loads a rich descriptor for a given service description
// generated by protoc-gen-go. Generated code contains an unexported symbol with
// a name like "_<Service>_serviceDesc" which is the service's description. It
// is used internally to register a service implementation with a GRPC server.
// But it can also be used by this package to retrieve the rich descriptor for
// the service.
func LoadServiceDescriptor(svc *grpc.ServiceDesc) (*desc.ServiceDescriptor, error) {
file, ok := svc.Metadata.(string)
if !ok {
return nil, fmt.Errorf("service %q has unexpected metadata: expecting a string; got %v", svc.ServiceName, svc.Metadata)
}
fd, err := desc.LoadFileDescriptor(file)
if err != nil {
return nil, err
}
d := fd.FindSymbol(svc.ServiceName)
if d == nil {
return nil, fmt.Errorf("file descriptor for %q has no element named %q", file, svc.ServiceName)
}
sd, ok := d.(*desc.ServiceDescriptor)
if !ok {
return nil, fmt.Errorf("file descriptor for %q has incorrect element named %q: expecting a service descriptor; got %v", file, svc.ServiceName, d)
}
return sd, nil
}