Skip to content

Commit 55ead9f

Browse files
cratelynconorsch
andcommitted
tonic-reflection: 🆕 use v1 reflection protobuffer definitions
this fixes hyperium#1685. in penumbra-zone/penumbra#4392, we observed that tonic servers do not properly support reflection when servicing a request sent by recent versions of [`grpcurl`], after [v1.8.8] began using `grpc.reflection.v1.ServerReflection`. (see fullstorydev/grpcurl#407) these lead to an error regarding an unexpected status code, like this: ``` ❯ grpcurl --version grpcurl v1.9.1 ❯ grpcurl -vv grpc.testnet.penumbra.zone:443 list Failed to list services: rpc error: code = Unknown desc = unexpected HTTP status code received from server: 405 (Method Not Allowed); malformed header: missing HTTP content-type ``` this adds the v1 reflection definition to `tonic-reflection`, which was observed as fixing these issues for our gRPC endpoint. ### 🩹 changes changes in this commet are as follows: * vendors the `v1` definition of [`reflection.proto`][proto]. * renames the (deprecated) `v1alpha` definition to `reflection_v1alpha.proto`. * `tonic_reflection::generated::grpc_reflection_v1` links to the generated Rust code (created by running `cargo run --package codegen`). * `tonic_reflection::generated::FILE_DESCRIPTOR_SET` is replaced by `tonic_reflection::generated::{FILE_DESCRIPTOR_SET_V1ALPHA, FILE_DESCRIPTOR_SET_V1}`. * `tonic_reflection::pb` now contains namespaced `tonic_reflection::pb::{v1alpha, v1}` submodules. (**NB: this is a breaking change to the public `tonic-reflection` API.**) * `tonic_reflection::server` is updated to use the generated `tonic_reflection::pb::v1` code. * `HttpsUriWithoutTlsSupport` is now gated behind the `tls` feature flag, because it is not used otherwise. [v1.8.8]: https://github.com/fullstorydev/grpcurl/releases/tag/v1.8.8 [proto]: https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1/reflection.proto [grpcurl]: https://github.com/fullstorydev/grpcurl --- fixes: hyperium#1685 x-ref: penumbra-zone/penumbra#4392 co-authored-by: Conor Schaefer <conor@penumbralabs.xyz>
1 parent 068421a commit 55ead9f

File tree

11 files changed

+671
-19
lines changed

11 files changed

+671
-19
lines changed

codegen/src/main.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,19 @@ fn main() {
2121
.parent()
2222
.unwrap()
2323
.join("tonic-reflection"),
24-
&["proto/reflection.proto"],
24+
&["proto/reflection_v1.proto"],
25+
&["proto"],
26+
&PathBuf::from("src/generated"),
27+
&PathBuf::from("src/generated/reflection_v1.bin"),
28+
true,
29+
true,
30+
);
31+
codegen(
32+
&PathBuf::from(std::env!("CARGO_MANIFEST_DIR"))
33+
.parent()
34+
.unwrap()
35+
.join("tonic-reflection"),
36+
&["proto/reflection_v1alpha.proto"],
2537
&["proto"],
2638
&PathBuf::from("src/generated"),
2739
&PathBuf::from("src/generated/reflection_v1alpha1.bin"),
+147
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Copyright 2016 The gRPC Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// Service exported by server reflection. A more complete description of how
16+
// server reflection works can be found at
17+
// https://github.com/grpc/grpc/blob/master/doc/server-reflection.md
18+
//
19+
// The canonical version of this proto can be found at
20+
// https://github.com/grpc/grpc-proto/blob/master/grpc/reflection/v1/reflection.proto
21+
22+
syntax = "proto3";
23+
24+
package grpc.reflection.v1;
25+
26+
option go_package = "google.golang.org/grpc/reflection/grpc_reflection_v1";
27+
option java_multiple_files = true;
28+
option java_package = "io.grpc.reflection.v1";
29+
option java_outer_classname = "ServerReflectionProto";
30+
31+
service ServerReflection {
32+
// The reflection service is structured as a bidirectional stream, ensuring
33+
// all related requests go to a single server.
34+
rpc ServerReflectionInfo(stream ServerReflectionRequest)
35+
returns (stream ServerReflectionResponse);
36+
}
37+
38+
// The message sent by the client when calling ServerReflectionInfo method.
39+
message ServerReflectionRequest {
40+
string host = 1;
41+
// To use reflection service, the client should set one of the following
42+
// fields in message_request. The server distinguishes requests by their
43+
// defined field and then handles them using corresponding methods.
44+
oneof message_request {
45+
// Find a proto file by the file name.
46+
string file_by_filename = 3;
47+
48+
// Find the proto file that declares the given fully-qualified symbol name.
49+
// This field should be a fully-qualified symbol name
50+
// (e.g. <package>.<service>[.<method>] or <package>.<type>).
51+
string file_containing_symbol = 4;
52+
53+
// Find the proto file which defines an extension extending the given
54+
// message type with the given field number.
55+
ExtensionRequest file_containing_extension = 5;
56+
57+
// Finds the tag numbers used by all known extensions of the given message
58+
// type, and appends them to ExtensionNumberResponse in an undefined order.
59+
// Its corresponding method is best-effort: it's not guaranteed that the
60+
// reflection service will implement this method, and it's not guaranteed
61+
// that this method will provide all extensions. Returns
62+
// StatusCode::UNIMPLEMENTED if it's not implemented.
63+
// This field should be a fully-qualified type name. The format is
64+
// <package>.<type>
65+
string all_extension_numbers_of_type = 6;
66+
67+
// List the full names of registered services. The content will not be
68+
// checked.
69+
string list_services = 7;
70+
}
71+
}
72+
73+
// The type name and extension number sent by the client when requesting
74+
// file_containing_extension.
75+
message ExtensionRequest {
76+
// Fully-qualified type name. The format should be <package>.<type>
77+
string containing_type = 1;
78+
int32 extension_number = 2;
79+
}
80+
81+
// The message sent by the server to answer ServerReflectionInfo method.
82+
message ServerReflectionResponse {
83+
string valid_host = 1;
84+
ServerReflectionRequest original_request = 2;
85+
// The server sets one of the following fields according to the message_request
86+
// in the request.
87+
oneof message_response {
88+
// This message is used to answer file_by_filename, file_containing_symbol,
89+
// file_containing_extension requests with transitive dependencies.
90+
// As the repeated label is not allowed in oneof fields, we use a
91+
// FileDescriptorResponse message to encapsulate the repeated fields.
92+
// The reflection service is allowed to avoid sending FileDescriptorProtos
93+
// that were previously sent in response to earlier requests in the stream.
94+
FileDescriptorResponse file_descriptor_response = 4;
95+
96+
// This message is used to answer all_extension_numbers_of_type requests.
97+
ExtensionNumberResponse all_extension_numbers_response = 5;
98+
99+
// This message is used to answer list_services requests.
100+
ListServiceResponse list_services_response = 6;
101+
102+
// This message is used when an error occurs.
103+
ErrorResponse error_response = 7;
104+
}
105+
}
106+
107+
// Serialized FileDescriptorProto messages sent by the server answering
108+
// a file_by_filename, file_containing_symbol, or file_containing_extension
109+
// request.
110+
message FileDescriptorResponse {
111+
// Serialized FileDescriptorProto messages. We avoid taking a dependency on
112+
// descriptor.proto, which uses proto2 only features, by making them opaque
113+
// bytes instead.
114+
repeated bytes file_descriptor_proto = 1;
115+
}
116+
117+
// A list of extension numbers sent by the server answering
118+
// all_extension_numbers_of_type request.
119+
message ExtensionNumberResponse {
120+
// Full name of the base type, including the package name. The format
121+
// is <package>.<type>
122+
string base_type_name = 1;
123+
repeated int32 extension_number = 2;
124+
}
125+
126+
// A list of ServiceResponse sent by the server answering list_services request.
127+
message ListServiceResponse {
128+
// The information of each service may be expanded in the future, so we use
129+
// ServiceResponse message to encapsulate it.
130+
repeated ServiceResponse service = 1;
131+
}
132+
133+
// The information of a single service used by ListServiceResponse to answer
134+
// list_services request.
135+
message ServiceResponse {
136+
// Full name of a registered service, including its package name. The format
137+
// is <package>.<service>
138+
string name = 1;
139+
}
140+
141+
// The error code and error message sent by the server when an error occurs.
142+
message ErrorResponse {
143+
// This field uses the error codes defined in grpc::StatusCode.
144+
int32 error_code = 1;
145+
string error_message = 2;
146+
}
147+

0 commit comments

Comments
 (0)