summaryrefslogtreecommitdiff
path: root/vendor/github.com/jhump/protoreflect/grpcreflect/server.go
blob: 7ff19127857466dc792427e8f5ef7aabb56d2a02 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package grpcreflect

import (
	"fmt"

	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"

	"github.com/jhump/protoreflect/desc"
)

// GRPCServer is the interface provided by a gRPC server. In addition to being a
// service registrar (for registering services and handlers), it also has an
// accessor for retrieving metadata about all registered services.
type GRPCServer = reflection.GRPCServer

// LoadServiceDescriptors loads the service descriptors for all services exposed by the
// given GRPC server.
func LoadServiceDescriptors(s GRPCServer) (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
}