serverreflection.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  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. v1reflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1"
  42. v1reflectionpb "google.golang.org/grpc/reflection/grpc_reflection_v1"
  43. v1alphareflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
  44. )
  45. // GRPCServer is the interface provided by a gRPC server. It is implemented by
  46. // *grpc.Server, but could also be implemented by other concrete types. It acts
  47. // as a registry, for accumulating the services exposed by the server.
  48. type GRPCServer interface {
  49. grpc.ServiceRegistrar
  50. ServiceInfoProvider
  51. }
  52. var _ GRPCServer = (*grpc.Server)(nil)
  53. // Register registers the server reflection service on the given gRPC server.
  54. // Both the v1 and v1alpha versions are registered.
  55. func Register(s GRPCServer) {
  56. svr := NewServerV1(ServerOptions{Services: s})
  57. v1alphareflectiongrpc.RegisterServerReflectionServer(s, asV1Alpha(svr))
  58. v1reflectiongrpc.RegisterServerReflectionServer(s, svr)
  59. }
  60. // RegisterV1 registers only the v1 version of the server reflection service
  61. // on the given gRPC server. Many clients may only support v1alpha so most
  62. // users should use Register instead, at least until clients have upgraded.
  63. func RegisterV1(s GRPCServer) {
  64. svr := NewServerV1(ServerOptions{Services: s})
  65. v1reflectiongrpc.RegisterServerReflectionServer(s, svr)
  66. }
  67. // ServiceInfoProvider is an interface used to retrieve metadata about the
  68. // services to expose.
  69. //
  70. // The reflection service is only interested in the service names, but the
  71. // signature is this way so that *grpc.Server implements it. So it is okay
  72. // for a custom implementation to return zero values for the
  73. // grpc.ServiceInfo values in the map.
  74. //
  75. // # Experimental
  76. //
  77. // Notice: This type is EXPERIMENTAL and may be changed or removed in a
  78. // later release.
  79. type ServiceInfoProvider interface {
  80. GetServiceInfo() map[string]grpc.ServiceInfo
  81. }
  82. // ExtensionResolver is the interface used to query details about extensions.
  83. // This interface is satisfied by protoregistry.GlobalTypes.
  84. //
  85. // # Experimental
  86. //
  87. // Notice: This type is EXPERIMENTAL and may be changed or removed in a
  88. // later release.
  89. type ExtensionResolver interface {
  90. protoregistry.ExtensionTypeResolver
  91. RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool)
  92. }
  93. // ServerOptions represents the options used to construct a reflection server.
  94. //
  95. // # Experimental
  96. //
  97. // Notice: This type is EXPERIMENTAL and may be changed or removed in a
  98. // later release.
  99. type ServerOptions struct {
  100. // The source of advertised RPC services. If not specified, the reflection
  101. // server will report an empty list when asked to list services.
  102. //
  103. // This value will typically be a *grpc.Server. But the set of advertised
  104. // services can be customized by wrapping a *grpc.Server or using an
  105. // alternate implementation that returns a custom set of service names.
  106. Services ServiceInfoProvider
  107. // Optional resolver used to load descriptors. If not specified,
  108. // protoregistry.GlobalFiles will be used.
  109. DescriptorResolver protodesc.Resolver
  110. // Optional resolver used to query for known extensions. If not specified,
  111. // protoregistry.GlobalTypes will be used.
  112. ExtensionResolver ExtensionResolver
  113. }
  114. // NewServer returns a reflection server implementation using the given options.
  115. // This can be used to customize behavior of the reflection service. Most usages
  116. // should prefer to use Register instead. For backwards compatibility reasons,
  117. // this returns the v1alpha version of the reflection server. For a v1 version
  118. // of the reflection server, see NewServerV1.
  119. //
  120. // # Experimental
  121. //
  122. // Notice: This function is EXPERIMENTAL and may be changed or removed in a
  123. // later release.
  124. func NewServer(opts ServerOptions) v1alphareflectiongrpc.ServerReflectionServer {
  125. return asV1Alpha(NewServerV1(opts))
  126. }
  127. // NewServerV1 returns a reflection server implementation using the given options.
  128. // This can be used to customize behavior of the reflection service. Most usages
  129. // should prefer to use Register instead.
  130. //
  131. // # Experimental
  132. //
  133. // Notice: This function is EXPERIMENTAL and may be changed or removed in a
  134. // later release.
  135. func NewServerV1(opts ServerOptions) v1reflectiongrpc.ServerReflectionServer {
  136. if opts.DescriptorResolver == nil {
  137. opts.DescriptorResolver = protoregistry.GlobalFiles
  138. }
  139. if opts.ExtensionResolver == nil {
  140. opts.ExtensionResolver = protoregistry.GlobalTypes
  141. }
  142. return &serverReflectionServer{
  143. s: opts.Services,
  144. descResolver: opts.DescriptorResolver,
  145. extResolver: opts.ExtensionResolver,
  146. }
  147. }
  148. type serverReflectionServer struct {
  149. v1alphareflectiongrpc.UnimplementedServerReflectionServer
  150. s ServiceInfoProvider
  151. descResolver protodesc.Resolver
  152. extResolver ExtensionResolver
  153. }
  154. // fileDescWithDependencies returns a slice of serialized fileDescriptors in
  155. // wire format ([]byte). The fileDescriptors will include fd and all the
  156. // transitive dependencies of fd with names not in sentFileDescriptors.
  157. func (s *serverReflectionServer) fileDescWithDependencies(fd protoreflect.FileDescriptor, sentFileDescriptors map[string]bool) ([][]byte, error) {
  158. var r [][]byte
  159. queue := []protoreflect.FileDescriptor{fd}
  160. for len(queue) > 0 {
  161. currentfd := queue[0]
  162. queue = queue[1:]
  163. if sent := sentFileDescriptors[currentfd.Path()]; len(r) == 0 || !sent {
  164. sentFileDescriptors[currentfd.Path()] = true
  165. fdProto := protodesc.ToFileDescriptorProto(currentfd)
  166. currentfdEncoded, err := proto.Marshal(fdProto)
  167. if err != nil {
  168. return nil, err
  169. }
  170. r = append(r, currentfdEncoded)
  171. }
  172. for i := 0; i < currentfd.Imports().Len(); i++ {
  173. queue = append(queue, currentfd.Imports().Get(i))
  174. }
  175. }
  176. return r, nil
  177. }
  178. // fileDescEncodingContainingSymbol finds the file descriptor containing the
  179. // given symbol, finds all of its previously unsent transitive dependencies,
  180. // does marshalling on them, and returns the marshalled result. The given symbol
  181. // can be a type, a service or a method.
  182. func (s *serverReflectionServer) fileDescEncodingContainingSymbol(name string, sentFileDescriptors map[string]bool) ([][]byte, error) {
  183. d, err := s.descResolver.FindDescriptorByName(protoreflect.FullName(name))
  184. if err != nil {
  185. return nil, err
  186. }
  187. return s.fileDescWithDependencies(d.ParentFile(), sentFileDescriptors)
  188. }
  189. // fileDescEncodingContainingExtension finds the file descriptor containing
  190. // given extension, finds all of its previously unsent transitive dependencies,
  191. // does marshalling on them, and returns the marshalled result.
  192. func (s *serverReflectionServer) fileDescEncodingContainingExtension(typeName string, extNum int32, sentFileDescriptors map[string]bool) ([][]byte, error) {
  193. xt, err := s.extResolver.FindExtensionByNumber(protoreflect.FullName(typeName), protoreflect.FieldNumber(extNum))
  194. if err != nil {
  195. return nil, err
  196. }
  197. return s.fileDescWithDependencies(xt.TypeDescriptor().ParentFile(), sentFileDescriptors)
  198. }
  199. // allExtensionNumbersForTypeName returns all extension numbers for the given type.
  200. func (s *serverReflectionServer) allExtensionNumbersForTypeName(name string) ([]int32, error) {
  201. var numbers []int32
  202. s.extResolver.RangeExtensionsByMessage(protoreflect.FullName(name), func(xt protoreflect.ExtensionType) bool {
  203. numbers = append(numbers, int32(xt.TypeDescriptor().Number()))
  204. return true
  205. })
  206. sort.Slice(numbers, func(i, j int) bool {
  207. return numbers[i] < numbers[j]
  208. })
  209. if len(numbers) == 0 {
  210. // maybe return an error if given type name is not known
  211. if _, err := s.descResolver.FindDescriptorByName(protoreflect.FullName(name)); err != nil {
  212. return nil, err
  213. }
  214. }
  215. return numbers, nil
  216. }
  217. // listServices returns the names of services this server exposes.
  218. func (s *serverReflectionServer) listServices() []*v1reflectionpb.ServiceResponse {
  219. serviceInfo := s.s.GetServiceInfo()
  220. resp := make([]*v1reflectionpb.ServiceResponse, 0, len(serviceInfo))
  221. for svc := range serviceInfo {
  222. resp = append(resp, &v1reflectionpb.ServiceResponse{Name: svc})
  223. }
  224. sort.Slice(resp, func(i, j int) bool {
  225. return resp[i].Name < resp[j].Name
  226. })
  227. return resp
  228. }
  229. // ServerReflectionInfo is the reflection service handler.
  230. func (s *serverReflectionServer) ServerReflectionInfo(stream v1reflectiongrpc.ServerReflection_ServerReflectionInfoServer) error {
  231. sentFileDescriptors := make(map[string]bool)
  232. for {
  233. in, err := stream.Recv()
  234. if err == io.EOF {
  235. return nil
  236. }
  237. if err != nil {
  238. return err
  239. }
  240. out := &v1reflectionpb.ServerReflectionResponse{
  241. ValidHost: in.Host,
  242. OriginalRequest: in,
  243. }
  244. switch req := in.MessageRequest.(type) {
  245. case *v1reflectionpb.ServerReflectionRequest_FileByFilename:
  246. var b [][]byte
  247. fd, err := s.descResolver.FindFileByPath(req.FileByFilename)
  248. if err == nil {
  249. b, err = s.fileDescWithDependencies(fd, sentFileDescriptors)
  250. }
  251. if err != nil {
  252. out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{
  253. ErrorResponse: &v1reflectionpb.ErrorResponse{
  254. ErrorCode: int32(codes.NotFound),
  255. ErrorMessage: err.Error(),
  256. },
  257. }
  258. } else {
  259. out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse{
  260. FileDescriptorResponse: &v1reflectionpb.FileDescriptorResponse{FileDescriptorProto: b},
  261. }
  262. }
  263. case *v1reflectionpb.ServerReflectionRequest_FileContainingSymbol:
  264. b, err := s.fileDescEncodingContainingSymbol(req.FileContainingSymbol, sentFileDescriptors)
  265. if err != nil {
  266. out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{
  267. ErrorResponse: &v1reflectionpb.ErrorResponse{
  268. ErrorCode: int32(codes.NotFound),
  269. ErrorMessage: err.Error(),
  270. },
  271. }
  272. } else {
  273. out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse{
  274. FileDescriptorResponse: &v1reflectionpb.FileDescriptorResponse{FileDescriptorProto: b},
  275. }
  276. }
  277. case *v1reflectionpb.ServerReflectionRequest_FileContainingExtension:
  278. typeName := req.FileContainingExtension.ContainingType
  279. extNum := req.FileContainingExtension.ExtensionNumber
  280. b, err := s.fileDescEncodingContainingExtension(typeName, extNum, sentFileDescriptors)
  281. if err != nil {
  282. out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{
  283. ErrorResponse: &v1reflectionpb.ErrorResponse{
  284. ErrorCode: int32(codes.NotFound),
  285. ErrorMessage: err.Error(),
  286. },
  287. }
  288. } else {
  289. out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse{
  290. FileDescriptorResponse: &v1reflectionpb.FileDescriptorResponse{FileDescriptorProto: b},
  291. }
  292. }
  293. case *v1reflectionpb.ServerReflectionRequest_AllExtensionNumbersOfType:
  294. extNums, err := s.allExtensionNumbersForTypeName(req.AllExtensionNumbersOfType)
  295. if err != nil {
  296. out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{
  297. ErrorResponse: &v1reflectionpb.ErrorResponse{
  298. ErrorCode: int32(codes.NotFound),
  299. ErrorMessage: err.Error(),
  300. },
  301. }
  302. } else {
  303. out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_AllExtensionNumbersResponse{
  304. AllExtensionNumbersResponse: &v1reflectionpb.ExtensionNumberResponse{
  305. BaseTypeName: req.AllExtensionNumbersOfType,
  306. ExtensionNumber: extNums,
  307. },
  308. }
  309. }
  310. case *v1reflectionpb.ServerReflectionRequest_ListServices:
  311. out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ListServicesResponse{
  312. ListServicesResponse: &v1reflectionpb.ListServiceResponse{
  313. Service: s.listServices(),
  314. },
  315. }
  316. default:
  317. return status.Errorf(codes.InvalidArgument, "invalid MessageRequest: %v", in.MessageRequest)
  318. }
  319. if err := stream.Send(out); err != nil {
  320. return err
  321. }
  322. }
  323. }