-
Notifications
You must be signed in to change notification settings - Fork 176
/
Copy pathserver.go
66 lines (59 loc) · 2.36 KB
/
server.go
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
package grpcreflect
import (
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"github.com/jhump/protoreflect/v2/protoresolve"
)
// 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]protoreflect.ServiceDescriptor, error) {
descs := map[string]protoreflect.ServiceDescriptor{}
for name, info := range s.GetServiceInfo() {
// See if the service info provides the schema in the service metadata.
sd, ok := info.Metadata.(protoreflect.ServiceDescriptor)
if !ok {
var err error
sd, err = findServiceDescriptor(name)
if err != nil {
return nil, err
}
}
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 exported 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) (protoreflect.ServiceDescriptor, error) {
// See if the service info provides the schema in the service metadata.
if sd, ok := svc.Metadata.(protoreflect.ServiceDescriptor); ok {
return sd, nil
}
sd, err := findServiceDescriptor(svc.ServiceName)
if err != nil {
return nil, fmt.Errorf("could not resolve descriptor for service %q: %w", svc.ServiceName, err)
}
return sd, nil
}
func findServiceDescriptor(name string) (protoreflect.ServiceDescriptor, error) {
d, err := protoregistry.GlobalFiles.FindDescriptorByName(protoreflect.FullName(name))
if err != nil {
return nil, fmt.Errorf("could not resolve descriptor for service %q: %w", name, err)
}
sd, ok := d.(protoreflect.ServiceDescriptor)
if !ok {
return nil, protoresolve.NewUnexpectedTypeError(protoresolve.DescriptorKindService, d, "")
}
return sd, nil
}