serverreflection.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /*
  2. *
  3. * Copyright 2016 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. /*
  19. Package reflection implements server reflection service.
  20. The service implemented is defined in:
  21. https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1alpha/reflection.proto.
  22. To register server reflection on a gRPC server:
  23. import "google.golang.org/grpc/reflection"
  24. s := grpc.NewServer()
  25. pb.RegisterYourOwnServer(s, &server{})
  26. // Register reflection service on gRPC server.
  27. reflection.Register(s)
  28. s.Serve(lis)
  29. */
  30. package reflection // import "google.golang.org/grpc/reflection"
  31. import (
  32. "io"
  33. "sort"
  34. "google.golang.org/grpc"
  35. "google.golang.org/grpc/codes"
  36. "google.golang.org/grpc/status"
  37. "google.golang.org/protobuf/proto"
  38. "google.golang.org/protobuf/reflect/protodesc"
  39. "google.golang.org/protobuf/reflect/protoreflect"
  40. "google.golang.org/protobuf/reflect/protoregistry"
  41. v1alphagrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
  42. v1alphapb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
  43. )
  44. // GRPCServer is the interface provided by a gRPC server. It is implemented by
  45. // *grpc.Server, but could also be implemented by other concrete types. It acts
  46. // as a registry, for accumulating the services exposed by the server.
  47. type GRPCServer interface {
  48. grpc.ServiceRegistrar
  49. ServiceInfoProvider
  50. }
  51. var _ GRPCServer = (*grpc.Server)(nil)
  52. // Register registers the server reflection service on the given gRPC server.
  53. func Register(s GRPCServer) {
  54. svr := NewServer(ServerOptions{Services: s})
  55. v1alphagrpc.RegisterServerReflectionServer(s, svr)
  56. }
  57. // ServiceInfoProvider is an interface used to retrieve metadata about the
  58. // services to expose.
  59. //
  60. // The reflection service is only interested in the service names, but the
  61. // signature is this way so that *grpc.Server implements it. So it is okay
  62. // for a custom implementation to return zero values for the
  63. // grpc.ServiceInfo values in the map.
  64. //
  65. // # Experimental
  66. //
  67. // Notice: This type is EXPERIMENTAL and may be changed or removed in a
  68. // later release.
  69. type ServiceInfoProvider interface {
  70. GetServiceInfo() map[string]grpc.ServiceInfo
  71. }
  72. // ExtensionResolver is the interface used to query details about extensions.
  73. // This interface is satisfied by protoregistry.GlobalTypes.
  74. //
  75. // # Experimental
  76. //
  77. // Notice: This type is EXPERIMENTAL and may be changed or removed in a
  78. // later release.
  79. type ExtensionResolver interface {
  80. protoregistry.ExtensionTypeResolver
  81. RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool)
  82. }
  83. // ServerOptions represents the options used to construct a reflection server.
  84. //
  85. // # Experimental
  86. //
  87. // Notice: This type is EXPERIMENTAL and may be changed or removed in a
  88. // later release.
  89. type ServerOptions struct {
  90. // The source of advertised RPC services. If not specified, the reflection
  91. // server will report an empty list when asked to list services.
  92. //
  93. // This value will typically be a *grpc.Server. But the set of advertised
  94. // services can be customized by wrapping a *grpc.Server or using an
  95. // alternate implementation that returns a custom set of service names.
  96. Services ServiceInfoProvider
  97. // Optional resolver used to load descriptors. If not specified,
  98. // protoregistry.GlobalFiles will be used.
  99. DescriptorResolver protodesc.Resolver
  100. // Optional resolver used to query for known extensions. If not specified,
  101. // protoregistry.GlobalTypes will be used.
  102. ExtensionResolver ExtensionResolver
  103. }
  104. // NewServer returns a reflection server implementation using the given options.
  105. // This can be used to customize behavior of the reflection service. Most usages
  106. // should prefer to use Register instead.
  107. //
  108. // # Experimental
  109. //
  110. // Notice: This function is EXPERIMENTAL and may be changed or removed in a
  111. // later release.
  112. func NewServer(opts ServerOptions) v1alphagrpc.ServerReflectionServer {
  113. if opts.DescriptorResolver == nil {
  114. opts.DescriptorResolver = protoregistry.GlobalFiles
  115. }
  116. if opts.ExtensionResolver == nil {
  117. opts.ExtensionResolver = protoregistry.GlobalTypes
  118. }
  119. return &serverReflectionServer{
  120. s: opts.Services,
  121. descResolver: opts.DescriptorResolver,
  122. extResolver: opts.ExtensionResolver,
  123. }
  124. }
  125. type serverReflectionServer struct {
  126. v1alphagrpc.UnimplementedServerReflectionServer
  127. s ServiceInfoProvider
  128. descResolver protodesc.Resolver
  129. extResolver ExtensionResolver
  130. }
  131. // fileDescWithDependencies returns a slice of serialized fileDescriptors in
  132. // wire format ([]byte). The fileDescriptors will include fd and all the
  133. // transitive dependencies of fd with names not in sentFileDescriptors.
  134. func (s *serverReflectionServer) fileDescWithDependencies(fd protoreflect.FileDescriptor, sentFileDescriptors map[string]bool) ([][]byte, error) {
  135. var r [][]byte
  136. queue := []protoreflect.FileDescriptor{fd}
  137. for len(queue) > 0 {
  138. currentfd := queue[0]
  139. queue = queue[1:]
  140. if sent := sentFileDescriptors[currentfd.Path()]; len(r) == 0 || !sent {
  141. sentFileDescriptors[currentfd.Path()] = true
  142. fdProto := protodesc.ToFileDescriptorProto(currentfd)
  143. currentfdEncoded, err := proto.Marshal(fdProto)
  144. if err != nil {
  145. return nil, err
  146. }
  147. r = append(r, currentfdEncoded)
  148. }
  149. for i := 0; i < currentfd.Imports().Len(); i++ {
  150. queue = append(queue, currentfd.Imports().Get(i))
  151. }
  152. }
  153. return r, nil
  154. }
  155. // fileDescEncodingContainingSymbol finds the file descriptor containing the
  156. // given symbol, finds all of its previously unsent transitive dependencies,
  157. // does marshalling on them, and returns the marshalled result. The given symbol
  158. // can be a type, a service or a method.
  159. func (s *serverReflectionServer) fileDescEncodingContainingSymbol(name string, sentFileDescriptors map[string]bool) ([][]byte, error) {
  160. d, err := s.descResolver.FindDescriptorByName(protoreflect.FullName(name))
  161. if err != nil {
  162. return nil, err
  163. }
  164. return s.fileDescWithDependencies(d.ParentFile(), sentFileDescriptors)
  165. }
  166. // fileDescEncodingContainingExtension finds the file descriptor containing
  167. // given extension, finds all of its previously unsent transitive dependencies,
  168. // does marshalling on them, and returns the marshalled result.
  169. func (s *serverReflectionServer) fileDescEncodingContainingExtension(typeName string, extNum int32, sentFileDescriptors map[string]bool) ([][]byte, error) {
  170. xt, err := s.extResolver.FindExtensionByNumber(protoreflect.FullName(typeName), protoreflect.FieldNumber(extNum))
  171. if err != nil {
  172. return nil, err
  173. }
  174. return s.fileDescWithDependencies(xt.TypeDescriptor().ParentFile(), sentFileDescriptors)
  175. }
  176. // allExtensionNumbersForTypeName returns all extension numbers for the given type.
  177. func (s *serverReflectionServer) allExtensionNumbersForTypeName(name string) ([]int32, error) {
  178. var numbers []int32
  179. s.extResolver.RangeExtensionsByMessage(protoreflect.FullName(name), func(xt protoreflect.ExtensionType) bool {
  180. numbers = append(numbers, int32(xt.TypeDescriptor().Number()))
  181. return true
  182. })
  183. sort.Slice(numbers, func(i, j int) bool {
  184. return numbers[i] < numbers[j]
  185. })
  186. if len(numbers) == 0 {
  187. // maybe return an error if given type name is not known
  188. if _, err := s.descResolver.FindDescriptorByName(protoreflect.FullName(name)); err != nil {
  189. return nil, err
  190. }
  191. }
  192. return numbers, nil
  193. }
  194. // listServices returns the names of services this server exposes.
  195. func (s *serverReflectionServer) listServices() []*v1alphapb.ServiceResponse {
  196. serviceInfo := s.s.GetServiceInfo()
  197. resp := make([]*v1alphapb.ServiceResponse, 0, len(serviceInfo))
  198. for svc := range serviceInfo {
  199. resp = append(resp, &v1alphapb.ServiceResponse{Name: svc})
  200. }
  201. sort.Slice(resp, func(i, j int) bool {
  202. return resp[i].Name < resp[j].Name
  203. })
  204. return resp
  205. }
  206. // ServerReflectionInfo is the reflection service handler.
  207. func (s *serverReflectionServer) ServerReflectionInfo(stream v1alphagrpc.ServerReflection_ServerReflectionInfoServer) error {
  208. sentFileDescriptors := make(map[string]bool)
  209. for {
  210. in, err := stream.Recv()
  211. if err == io.EOF {
  212. return nil
  213. }
  214. if err != nil {
  215. return err
  216. }
  217. out := &v1alphapb.ServerReflectionResponse{
  218. ValidHost: in.Host,
  219. OriginalRequest: in,
  220. }
  221. switch req := in.MessageRequest.(type) {
  222. case *v1alphapb.ServerReflectionRequest_FileByFilename:
  223. var b [][]byte
  224. fd, err := s.descResolver.FindFileByPath(req.FileByFilename)
  225. if err == nil {
  226. b, err = s.fileDescWithDependencies(fd, sentFileDescriptors)
  227. }
  228. if err != nil {
  229. out.MessageResponse = &v1alphapb.ServerReflectionResponse_ErrorResponse{
  230. ErrorResponse: &v1alphapb.ErrorResponse{
  231. ErrorCode: int32(codes.NotFound),
  232. ErrorMessage: err.Error(),
  233. },
  234. }
  235. } else {
  236. out.MessageResponse = &v1alphapb.ServerReflectionResponse_FileDescriptorResponse{
  237. FileDescriptorResponse: &v1alphapb.FileDescriptorResponse{FileDescriptorProto: b},
  238. }
  239. }
  240. case *v1alphapb.ServerReflectionRequest_FileContainingSymbol:
  241. b, err := s.fileDescEncodingContainingSymbol(req.FileContainingSymbol, sentFileDescriptors)
  242. if err != nil {
  243. out.MessageResponse = &v1alphapb.ServerReflectionResponse_ErrorResponse{
  244. ErrorResponse: &v1alphapb.ErrorResponse{
  245. ErrorCode: int32(codes.NotFound),
  246. ErrorMessage: err.Error(),
  247. },
  248. }
  249. } else {
  250. out.MessageResponse = &v1alphapb.ServerReflectionResponse_FileDescriptorResponse{
  251. FileDescriptorResponse: &v1alphapb.FileDescriptorResponse{FileDescriptorProto: b},
  252. }
  253. }
  254. case *v1alphapb.ServerReflectionRequest_FileContainingExtension:
  255. typeName := req.FileContainingExtension.ContainingType
  256. extNum := req.FileContainingExtension.ExtensionNumber
  257. b, err := s.fileDescEncodingContainingExtension(typeName, extNum, sentFileDescriptors)
  258. if err != nil {
  259. out.MessageResponse = &v1alphapb.ServerReflectionResponse_ErrorResponse{
  260. ErrorResponse: &v1alphapb.ErrorResponse{
  261. ErrorCode: int32(codes.NotFound),
  262. ErrorMessage: err.Error(),
  263. },
  264. }
  265. } else {
  266. out.MessageResponse = &v1alphapb.ServerReflectionResponse_FileDescriptorResponse{
  267. FileDescriptorResponse: &v1alphapb.FileDescriptorResponse{FileDescriptorProto: b},
  268. }
  269. }
  270. case *v1alphapb.ServerReflectionRequest_AllExtensionNumbersOfType:
  271. extNums, err := s.allExtensionNumbersForTypeName(req.AllExtensionNumbersOfType)
  272. if err != nil {
  273. out.MessageResponse = &v1alphapb.ServerReflectionResponse_ErrorResponse{
  274. ErrorResponse: &v1alphapb.ErrorResponse{
  275. ErrorCode: int32(codes.NotFound),
  276. ErrorMessage: err.Error(),
  277. },
  278. }
  279. } else {
  280. out.MessageResponse = &v1alphapb.ServerReflectionResponse_AllExtensionNumbersResponse{
  281. AllExtensionNumbersResponse: &v1alphapb.ExtensionNumberResponse{
  282. BaseTypeName: req.AllExtensionNumbersOfType,
  283. ExtensionNumber: extNums,
  284. },
  285. }
  286. }
  287. case *v1alphapb.ServerReflectionRequest_ListServices:
  288. out.MessageResponse = &v1alphapb.ServerReflectionResponse_ListServicesResponse{
  289. ListServicesResponse: &v1alphapb.ListServiceResponse{
  290. Service: s.listServices(),
  291. },
  292. }
  293. default:
  294. return status.Errorf(codes.InvalidArgument, "invalid MessageRequest: %v", in.MessageRequest)
  295. }
  296. if err := stream.Send(out); err != nil {
  297. return err
  298. }
  299. }
  300. }