xref: /aosp_15_r20/external/grpc-grpc/doc/server-reflection.md (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1*cc02d7e2SAndroid Build Coastguard WorkerGRPC Server Reflection Protocol
2*cc02d7e2SAndroid Build Coastguard Worker===============================
3*cc02d7e2SAndroid Build Coastguard Worker
4*cc02d7e2SAndroid Build Coastguard WorkerThis document describes server reflection as an optional extension for servers
5*cc02d7e2SAndroid Build Coastguard Workerto assist clients in runtime construction of requests without having stub
6*cc02d7e2SAndroid Build Coastguard Workerinformation precompiled into the client.
7*cc02d7e2SAndroid Build Coastguard Worker
8*cc02d7e2SAndroid Build Coastguard WorkerThe primary usecase for server reflection is to write (typically) command line
9*cc02d7e2SAndroid Build Coastguard Workerdebugging tools for talking to a grpc server. In particular, such a tool will
10*cc02d7e2SAndroid Build Coastguard Workertake in a method and a payload (in human readable text format) send it to the
11*cc02d7e2SAndroid Build Coastguard Workerserver (typically in binary proto wire format), and then take the response and
12*cc02d7e2SAndroid Build Coastguard Workerdecode it to text to present to the user.
13*cc02d7e2SAndroid Build Coastguard Worker
14*cc02d7e2SAndroid Build Coastguard WorkerThis broadly involves two problems: determining what formats (which protobuf
15*cc02d7e2SAndroid Build Coastguard Workermessages) a server’s method uses, and determining how to convert messages
16*cc02d7e2SAndroid Build Coastguard Workerbetween human readable format and the (likely binary) wire format.
17*cc02d7e2SAndroid Build Coastguard Worker
18*cc02d7e2SAndroid Build Coastguard Worker## Method reflection
19*cc02d7e2SAndroid Build Coastguard Worker
20*cc02d7e2SAndroid Build Coastguard WorkerWe want to be able to answer the following queries:
21*cc02d7e2SAndroid Build Coastguard Worker 1. What methods does a server export?
22*cc02d7e2SAndroid Build Coastguard Worker 2. For a particular method, how do we call it?
23*cc02d7e2SAndroid Build Coastguard WorkerSpecifically, what are the names of the methods, are those methods unary or
24*cc02d7e2SAndroid Build Coastguard Workerstreaming, and what are the types of the argument and result?
25*cc02d7e2SAndroid Build Coastguard Worker
26*cc02d7e2SAndroid Build Coastguard WorkerThe first version of the protocol is here:
27*cc02d7e2SAndroid Build Coastguard Workerhttps://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1/reflection.proto
28*cc02d7e2SAndroid Build Coastguard Worker
29*cc02d7e2SAndroid Build Coastguard WorkerNote that a server is under no obligation to return a complete list of all
30*cc02d7e2SAndroid Build Coastguard Workermethods it supports. For example, a reverse proxy may support server reflection
31*cc02d7e2SAndroid Build Coastguard Workerfor methods implemented directly on the proxy but not enumerate all methods
32*cc02d7e2SAndroid Build Coastguard Workersupported by its backends.
33*cc02d7e2SAndroid Build Coastguard Worker
34*cc02d7e2SAndroid Build Coastguard Worker
35*cc02d7e2SAndroid Build Coastguard Worker### Open questions on method reflection
36*cc02d7e2SAndroid Build Coastguard Worker * Consider how to extend this protocol to support non-protobuf methods.
37*cc02d7e2SAndroid Build Coastguard Worker
38*cc02d7e2SAndroid Build Coastguard Worker## Argument reflection
39*cc02d7e2SAndroid Build Coastguard WorkerThe second half of the problem is converting between the human readable
40*cc02d7e2SAndroid Build Coastguard Workerinput/output of a debugging tool and the binary format understood by the
41*cc02d7e2SAndroid Build Coastguard Workermethod.
42*cc02d7e2SAndroid Build Coastguard Worker
43*cc02d7e2SAndroid Build Coastguard WorkerThis is obviously dependent on protocol type. At one extreme, if both the
44*cc02d7e2SAndroid Build Coastguard Workerserver and the debugging tool accept JSON, there may be no need for such a
45*cc02d7e2SAndroid Build Coastguard Workerconversion in the first place. At the opposite extreme, a server using a custom
46*cc02d7e2SAndroid Build Coastguard Workerbinary format has no hope of being supported by a generic system. The
47*cc02d7e2SAndroid Build Coastguard Workerintermediate interesting common case is a server which speaks binary-proto and
48*cc02d7e2SAndroid Build Coastguard Workera debugging client which speaks either ascii-proto or json-proto.
49*cc02d7e2SAndroid Build Coastguard Worker
50*cc02d7e2SAndroid Build Coastguard WorkerOne approach would be to require servers directly support human readable input.
51*cc02d7e2SAndroid Build Coastguard WorkerIn the future method reflection may be extended to document such support,
52*cc02d7e2SAndroid Build Coastguard Workershould it become widespread or standardized.
53*cc02d7e2SAndroid Build Coastguard Worker
54*cc02d7e2SAndroid Build Coastguard Worker## Protobuf descriptors
55*cc02d7e2SAndroid Build Coastguard Worker
56*cc02d7e2SAndroid Build Coastguard WorkerA second would be for the server to export its
57*cc02d7e2SAndroid Build Coastguard Workergoogle::protobuf::DescriptorDatabase over the wire. This is very easy to
58*cc02d7e2SAndroid Build Coastguard Workerimplement in C++, and Google implementations of a similar protocol already
59*cc02d7e2SAndroid Build Coastguard Workerexist in C++, Go, and Java.
60*cc02d7e2SAndroid Build Coastguard Worker
61*cc02d7e2SAndroid Build Coastguard WorkerThis protocol mostly returns FileDescriptorProtos, which are a proto encoding
62*cc02d7e2SAndroid Build Coastguard Workerof a parsed .proto file. It supports four queries:
63*cc02d7e2SAndroid Build Coastguard Worker 1. The FileDescriptorProto for a given file name
64*cc02d7e2SAndroid Build Coastguard Worker 2. The FileDescriptorProto for the file with a given symbol
65*cc02d7e2SAndroid Build Coastguard Worker 3. The FileDescriptorProto for the file with a given extension
66*cc02d7e2SAndroid Build Coastguard Worker 4. The list of known extension tag numbers of a given type
67*cc02d7e2SAndroid Build Coastguard Worker
68*cc02d7e2SAndroid Build Coastguard WorkerThese directly correspond to the methods of
69*cc02d7e2SAndroid Build Coastguard Workergoogle::protobuf::DescriptorDatabase. Note that this protocol includes support
70*cc02d7e2SAndroid Build Coastguard Workerfor extensions, which have been removed from proto3 but are still in widespread
71*cc02d7e2SAndroid Build Coastguard Workeruse in Google’s codebase.
72*cc02d7e2SAndroid Build Coastguard Worker
73*cc02d7e2SAndroid Build Coastguard WorkerBecause most usecases will require also requesting the transitive dependencies
74*cc02d7e2SAndroid Build Coastguard Workerof requested files, the queries will also return all transitive dependencies of
75*cc02d7e2SAndroid Build Coastguard Workerthe returned file. Should interesting usecases for non-transitive queries turn
76*cc02d7e2SAndroid Build Coastguard Workerup later, we can easily extend the protocol to support them.
77*cc02d7e2SAndroid Build Coastguard Worker
78*cc02d7e2SAndroid Build Coastguard Worker### Reverse proxy traversal
79*cc02d7e2SAndroid Build Coastguard Worker
80*cc02d7e2SAndroid Build Coastguard WorkerOne potential issue with naive reverse proxies is that, while any individual
81*cc02d7e2SAndroid Build Coastguard Workerserver will have a consistent and valid picture of the proto DB which is
82*cc02d7e2SAndroid Build Coastguard Workersufficient to handle incoming requests, incompatibilities will arise if the
83*cc02d7e2SAndroid Build Coastguard Workerbackend servers have a mix of builds. For example, if a given message is moved
84*cc02d7e2SAndroid Build Coastguard Workerfrom foo.proto to bar.proto, and the client requests foo.proto from an old
85*cc02d7e2SAndroid Build Coastguard Workerserver and bar.proto from a new server, the resulting database will have a
86*cc02d7e2SAndroid Build Coastguard Workerdouble definition.
87*cc02d7e2SAndroid Build Coastguard Worker
88*cc02d7e2SAndroid Build Coastguard WorkerTo solve this problem, the protocol is structured as a bidirectional stream,
89*cc02d7e2SAndroid Build Coastguard Workerensuring all related requests go to a single server. This has the additional
90*cc02d7e2SAndroid Build Coastguard Workerbenefit that overlapping recursive requests don’t require sending a lot of
91*cc02d7e2SAndroid Build Coastguard Workerredundant information, because there is a single stream to maintain context
92*cc02d7e2SAndroid Build Coastguard Workerbetween queries.
93*cc02d7e2SAndroid Build Coastguard Worker
94*cc02d7e2SAndroid Build Coastguard Worker```
95*cc02d7e2SAndroid Build Coastguard Workerpackage grpc.reflection.v1alpha;
96*cc02d7e2SAndroid Build Coastguard Workermessage DescriptorDatabaseRequest {
97*cc02d7e2SAndroid Build Coastguard Worker  string host = 1;
98*cc02d7e2SAndroid Build Coastguard Worker  oneof message_request {
99*cc02d7e2SAndroid Build Coastguard Worker    string files_for_file_name = 3;
100*cc02d7e2SAndroid Build Coastguard Worker    string files_for_symbol_name = 4;
101*cc02d7e2SAndroid Build Coastguard Worker    FileContainingExtensionRequest file_containing_extension = 5;
102*cc02d7e2SAndroid Build Coastguard Worker    string list_all_extensions_of_type = 6;
103*cc02d7e2SAndroid Build Coastguard Worker  }
104*cc02d7e2SAndroid Build Coastguard Worker}
105*cc02d7e2SAndroid Build Coastguard Worker
106*cc02d7e2SAndroid Build Coastguard Workermessage FileContainingExtensionRequest {
107*cc02d7e2SAndroid Build Coastguard Worker  string base_message = 1;
108*cc02d7e2SAndroid Build Coastguard Worker  int64 extension_id = 2;
109*cc02d7e2SAndroid Build Coastguard Worker}
110*cc02d7e2SAndroid Build Coastguard Worker
111*cc02d7e2SAndroid Build Coastguard Workermessage DescriptorDatabaseResponse {
112*cc02d7e2SAndroid Build Coastguard Worker  string valid_host = 1;
113*cc02d7e2SAndroid Build Coastguard Worker  DescriptorDatabaseRequest original_request = 2;
114*cc02d7e2SAndroid Build Coastguard Worker  oneof message_response {
115*cc02d7e2SAndroid Build Coastguard Worker    // These are proto2 type google.protobuf.FileDescriptorProto, but
116*cc02d7e2SAndroid Build Coastguard Worker    // we avoid taking a dependency on descriptor.proto, which uses
117*cc02d7e2SAndroid Build Coastguard Worker    // proto2 only features, by making them opaque
118*cc02d7e2SAndroid Build Coastguard Worker    // bytes instead
119*cc02d7e2SAndroid Build Coastguard Worker    repeated bytes fd_proto = 4;
120*cc02d7e2SAndroid Build Coastguard Worker    ListAllExtensionsResponse extensions_response = 5;
121*cc02d7e2SAndroid Build Coastguard Worker    // Notably includes error code 5, NOT FOUND
122*cc02d7e2SAndroid Build Coastguard Worker    int32 error_code = 6;
123*cc02d7e2SAndroid Build Coastguard Worker  }
124*cc02d7e2SAndroid Build Coastguard Worker}
125*cc02d7e2SAndroid Build Coastguard Worker
126*cc02d7e2SAndroid Build Coastguard Workermessage ListAllExtensionsResponse {
127*cc02d7e2SAndroid Build Coastguard Worker  string base_type_name;
128*cc02d7e2SAndroid Build Coastguard Worker  repeated int64 extension_number;
129*cc02d7e2SAndroid Build Coastguard Worker}
130*cc02d7e2SAndroid Build Coastguard Worker
131*cc02d7e2SAndroid Build Coastguard Workerservice ProtoDescriptorDatabase {
132*cc02d7e2SAndroid Build Coastguard Worker  rpc DescriptorDatabaseInfo(stream DescriptorDatabaseRequest) returns (stream DescriptorDatabaseResponse);
133*cc02d7e2SAndroid Build Coastguard Worker}
134*cc02d7e2SAndroid Build Coastguard Worker```
135*cc02d7e2SAndroid Build Coastguard Worker
136*cc02d7e2SAndroid Build Coastguard WorkerAny given request must either result in an error code or an answer, usually in
137*cc02d7e2SAndroid Build Coastguard Workerthe form of a  series of FileDescriptorProtos with the requested file itself
138*cc02d7e2SAndroid Build Coastguard Workerand all previously unsent transitive imports of that file. Servers may track
139*cc02d7e2SAndroid Build Coastguard Workerwhich FileDescriptorProtos have been sent on a given stream, for a given value
140*cc02d7e2SAndroid Build Coastguard Workerof valid_host, and avoid sending them repeatedly for overlapping requests.
141*cc02d7e2SAndroid Build Coastguard Worker
142*cc02d7e2SAndroid Build Coastguard Worker| message_request message     | Result                                          |
143*cc02d7e2SAndroid Build Coastguard Worker| --------------------------- | ----------------------------------------------- |
144*cc02d7e2SAndroid Build Coastguard Worker| files_for_file_name         | transitive closure of file name                 |
145*cc02d7e2SAndroid Build Coastguard Worker| files_for_symbol_name       | transitive closure file containing symbol       |
146*cc02d7e2SAndroid Build Coastguard Worker| file_containing_extension   | transitive closure of file containing a given extension number of a given symbol |
147*cc02d7e2SAndroid Build Coastguard Worker| list_all_extensions_of_type | ListAllExtensionsResponse containing all known extension numbers of a given type |
148*cc02d7e2SAndroid Build Coastguard Worker
149*cc02d7e2SAndroid Build Coastguard WorkerAt some point it would make sense to additionally also support any.proto’s
150*cc02d7e2SAndroid Build Coastguard Workerformat. Note that known any.proto messages can be queried by symbol using this
151*cc02d7e2SAndroid Build Coastguard Workerprotocol even without any such support, by parsing the url and extracting the
152*cc02d7e2SAndroid Build Coastguard Workersymbol name from it.
153*cc02d7e2SAndroid Build Coastguard Worker
154*cc02d7e2SAndroid Build Coastguard Worker## Language specific implementation thoughts
155*cc02d7e2SAndroid Build Coastguard WorkerAll of the information needed to implement Proto reflection is available to the
156*cc02d7e2SAndroid Build Coastguard Workercode generator, but I’m not certain we actually generate this in every
157*cc02d7e2SAndroid Build Coastguard Workerlanguage. If the proto implementation in the  language doesn’t have something
158*cc02d7e2SAndroid Build Coastguard Workerlike google::protobuf::DescriptorPool the grpc implementation for that language
159*cc02d7e2SAndroid Build Coastguard Workerwill need to index those FileDescriptorProtos by file and symbol and imports.
160*cc02d7e2SAndroid Build Coastguard Worker
161*cc02d7e2SAndroid Build Coastguard WorkerOne issue is that some grpc implementations are very loosely coupled with
162*cc02d7e2SAndroid Build Coastguard Workerprotobufs; in such implementations it probably makes sense to split apart these
163*cc02d7e2SAndroid Build Coastguard Workerreflection APIs so as not to take an additional proto dependency.
164*cc02d7e2SAndroid Build Coastguard Worker
165*cc02d7e2SAndroid Build Coastguard Worker## Known Implementations
166*cc02d7e2SAndroid Build Coastguard Worker
167*cc02d7e2SAndroid Build Coastguard WorkerEnabling server reflection differs language-to-language. Here are links to docs relevant to
168*cc02d7e2SAndroid Build Coastguard Workereach language:
169*cc02d7e2SAndroid Build Coastguard Worker
170*cc02d7e2SAndroid Build Coastguard Worker- [Java](https://github.com/grpc/grpc-java/blob/master/documentation/server-reflection-tutorial.md#enable-server-reflection)
171*cc02d7e2SAndroid Build Coastguard Worker- [Go](https://github.com/grpc/grpc-go/blob/master/Documentation/server-reflection-tutorial.md#enable-server-reflection)
172*cc02d7e2SAndroid Build Coastguard Worker- [C++](https://grpc.io/grpc/cpp/md_doc_server_reflection_tutorial.html)
173*cc02d7e2SAndroid Build Coastguard Worker- [Python](https://github.com/grpc/grpc/blob/master/doc/python/server_reflection.md)
174*cc02d7e2SAndroid Build Coastguard Worker- Ruby: not yet implemented [#2567](https://github.com/grpc/grpc/issues/2567)
175*cc02d7e2SAndroid Build Coastguard Worker- Node: not yet implemented [#2568](https://github.com/grpc/grpc/issues/2568)
176