Skip to content

Commit 20ae1ce

Browse files
committed
Updates reflection server implementation
This change updates jen20's work in hyperium#340 to work with the file descriptor set changes that landed in prost 0.7. * Updates branch with new changes from master * Updates server to use tokio 1.0 symantics * `tonic_build::Builder::include_file_descriptor_set` -> `file_descriptor_set_path`, which matchesprost.
1 parent 59514ec commit 20ae1ce

File tree

10 files changed

+74
-41
lines changed

10 files changed

+74
-41
lines changed

Cargo.toml

-5
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,3 @@ members = [
1919
"tests/extern_path/my_application",
2020
"tests/integration_tests"
2121
]
22-
23-
[replace]
24-
'prost:0.6.1' = { git = "https://github.com/jen20/prost", branch = "jen20/file-descriptor-set" }
25-
'prost-build:0.6.1' = { git = "https://github.com/jen20/prost", branch = "jen20/file-descriptor-set" }
26-
'prost-types:0.6.1' = { git = "https://github.com/jen20/prost", branch = "jen20/file-descriptor-set" }

examples/README.md

+8
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,14 @@ $ cargo run --bin tls-server
9494
$ cargo run --bin health-server
9595
```
9696

97+
## Reflection Service
98+
99+
### Server
100+
101+
```bash
102+
$ cargo run --bin reflection-server
103+
```
104+
97105
## Tower Middleware
98106

99107
### Server

examples/build.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
1+
use std::env;
2+
use std::path::PathBuf;
3+
14
fn main() {
5+
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
6+
27
tonic_build::configure()
38
.type_attribute("routeguide.Point", "#[derive(Hash)]")
49
.compile(&["proto/routeguide/route_guide.proto"], &["proto"])
510
.unwrap();
611

7-
tonic_build::compile_protos("proto/helloworld/helloworld.proto").unwrap();
12+
tonic_build::configure()
13+
.file_descriptor_set_path(out_dir.join("helloworld_descriptor.bin"))
14+
.compile(&["proto/helloworld/helloworld.proto"], &["proto"])
15+
.unwrap();
16+
817
tonic_build::compile_protos("proto/echo/echo.proto").unwrap();
18+
919
tonic_build::compile_protos("proto/google/pubsub/pubsub.proto").unwrap();
1020
}

examples/src/reflection/server.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use tonic::{Request, Response, Status};
44
mod proto {
55
tonic::include_proto!("helloworld");
66

7-
pub(crate) const FILE_DESCRIPTOR_SET: &'static [u8] = tonic::include_file_descriptor_set!();
7+
pub(crate) const HELLO_WORLD_DESCRIPTOR_SET: &'static [u8] =
8+
include_bytes!(concat!(env!("OUT_DIR"), "/helloworld_descriptor.bin"));
89
}
910

1011
#[derive(Default)]
@@ -27,16 +28,16 @@ impl proto::greeter_server::Greeter for MyGreeter {
2728

2829
#[tokio::main]
2930
async fn main() -> Result<(), Box<dyn std::error::Error>> {
30-
let service = tonic_reflection::server::Builder::configure()
31-
.register_encoded_file_descriptor_set(proto::FILE_DESCRIPTOR_SET)
31+
let reflection_service = tonic_reflection::server::Builder::configure()
32+
.register_encoded_file_descriptor_set(proto::HELLO_WORLD_DESCRIPTOR_SET)
3233
.build()
3334
.unwrap();
3435

3536
let addr = "[::1]:50052".parse().unwrap();
3637
let greeter = MyGreeter::default();
3738

3839
Server::builder()
39-
.add_service(service)
40+
.add_service(reflection_service)
4041
.add_service(proto::greeter_server::GreeterServer::new(greeter))
4142
.serve(addr)
4243
.await?;

tonic-build/src/prost.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub fn configure() -> Builder {
1212
Builder {
1313
build_client: true,
1414
build_server: true,
15-
include_file_descriptor_set: false,
15+
file_descriptor_set_path: None,
1616
out_dir: None,
1717
extern_path: Vec::new(),
1818
field_attributes: Vec::new(),
@@ -181,7 +181,7 @@ impl prost_build::ServiceGenerator for ServiceGenerator {
181181
pub struct Builder {
182182
pub(crate) build_client: bool,
183183
pub(crate) build_server: bool,
184-
pub(crate) include_file_descriptor_set: bool,
184+
pub(crate) file_descriptor_set_path: Option<PathBuf>,
185185
pub(crate) extern_path: Vec<(String, String)>,
186186
pub(crate) field_attributes: Vec<(String, String)>,
187187
pub(crate) type_attributes: Vec<(String, String)>,
@@ -207,8 +207,8 @@ impl Builder {
207207

208208
/// Generate a file containing the encoded `prost_types::FileDescriptorSet` for protocol buffers
209209
/// modules. This is required for implementing gRPC Server Reflection.
210-
pub fn include_file_descriptor_set(mut self, include: bool) -> Self {
211-
self.include_file_descriptor_set = include;
210+
pub fn file_descriptor_set_path(mut self, path: impl AsRef<Path>) -> Self {
211+
self.file_descriptor_set_path = Some(path.as_ref().to_path_buf());
212212
self
213213
}
214214

@@ -296,9 +296,11 @@ impl Builder {
296296
let format = self.format;
297297

298298
config.out_dir(out_dir.clone());
299-
if self.include_file_descriptor_set {
300-
config.include_file_descriptor_set();
299+
300+
if let Some(path) = self.file_descriptor_set_path.as_ref() {
301+
config.file_descriptor_set_path(path);
301302
}
303+
302304
for (proto_path, rust_path) in self.extern_path.iter() {
303305
config.extern_path(proto_path, rust_path);
304306
}

tonic-health/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "tonic-health"
33
version = "0.3.0"
4-
authors = ["James Nugent <[email protected]>"]
4+
authors = ["James Nugent <[email protected]>", "Samani G. Gikandi <[email protected]>"]
55
edition = "2018"
66
license = "MIT"
77
repository = "https://github.com/hyperium/tonic"

tonic-reflection/Cargo.toml

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "tonic-reflection"
3-
version = "0.1.0"
3+
version = "0.4.0"
44
authors = ["James Nugent <[email protected]>"]
55
edition = "2018"
66
license = "MIT"
@@ -14,11 +14,12 @@ categories = ["network-programming", "asynchronous"]
1414
keywords = ["rpc", "grpc", "async", "reflection"]
1515

1616
[dependencies]
17-
bytes = "0.5"
18-
prost = "0.6"
19-
prost-types = "0.6"
20-
tokio = { version = "0.2", features = ["sync", "stream"] }
21-
tonic = { version = "0.2", path = "../tonic", features = ["codegen", "prost"] }
17+
bytes = "1.0"
18+
prost = "0.7"
19+
prost-types = "0.7"
20+
tokio = { version = "1.0", features = ["sync"] }
21+
tonic = { version = "0.4", path = "../tonic", features = ["codegen", "prost"] }
22+
tokio-stream = "0.1"
2223

2324
[build-dependencies]
24-
tonic-build = { version = "0.2", path = "../tonic-build" }
25+
tonic-build = { version = "0.4", path = "../tonic-build" }

tonic-reflection/build.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1+
use std::env;
2+
use std::path::PathBuf;
3+
14
fn main() -> Result<(), Box<dyn std::error::Error>> {
5+
let reflection_descriptors =
6+
PathBuf::from(env::var("OUT_DIR").unwrap()).join("reflection_descriptor.bin");
7+
28
tonic_build::configure()
3-
.include_file_descriptor_set(true)
9+
.file_descriptor_set_path(&reflection_descriptors)
410
.build_server(true)
511
.build_client(false)
612
.format(true)

tonic-reflection/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ mod proto {
1818
#![allow(unreachable_pub)]
1919
tonic::include_proto!("grpc.reflection.v1alpha");
2020

21-
pub(crate) const FILE_DESCRIPTOR_SET: &'static [u8] = tonic::include_file_descriptor_set!();
21+
pub(crate) const REFLECTION_DESCRIPTOR_SET: &'static [u8] =
22+
include_bytes!(concat!(env!("OUT_DIR"), "/reflection_descriptor.bin"));
2223
}
2324

2425
/// Implementation of the server component of gRPC Server Reflection.

tonic-reflection/src/server.rs

+24-15
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
1-
use crate::proto::server_reflection_request::MessageRequest;
2-
use crate::proto::server_reflection_response::MessageResponse;
3-
use crate::proto::server_reflection_server::{ServerReflection, ServerReflectionServer};
4-
use crate::proto::{
5-
FileDescriptorResponse, ListServiceResponse, ServerReflectionRequest, ServerReflectionResponse,
6-
ServiceResponse,
7-
};
1+
use std::collections::HashMap;
2+
use std::fmt::{Display, Formatter};
3+
use std::pin::Pin;
4+
use std::sync::Arc;
5+
86
use prost::{DecodeError, Message};
97
use prost_types::{
108
DescriptorProto, EnumDescriptorProto, FieldDescriptorProto, FileDescriptorProto,
119
FileDescriptorSet,
1210
};
13-
use std::collections::HashMap;
14-
use std::fmt::{Display, Formatter};
15-
use std::sync::Arc;
16-
use tokio::stream::StreamExt;
1711
use tokio::sync::mpsc;
12+
use tokio_stream::wrappers::ReceiverStream;
13+
use tokio_stream::{Stream, StreamExt};
1814
use tonic::{Request, Response, Status, Streaming};
1915

16+
use crate::proto::server_reflection_request::MessageRequest;
17+
use crate::proto::server_reflection_response::MessageResponse;
18+
use crate::proto::server_reflection_server::{ServerReflection, ServerReflectionServer};
19+
use crate::proto::{
20+
FileDescriptorResponse, ListServiceResponse, ServerReflectionRequest, ServerReflectionResponse,
21+
ServiceResponse,
22+
};
23+
2024
/// Represents an error in the construction of a gRPC Reflection Service.
2125
#[derive(Debug)]
2226
pub enum Error {
@@ -78,6 +82,8 @@ impl<'b> Builder<'b> {
7882

7983
/// Registers a byte slice containing an encoded `prost_types::FileDescriptorSet` with
8084
/// the gRPC Reflection Service builder.
85+
///
86+
/// This can be called multiple times to append new descriptors to the serivce.
8187
pub fn register_encoded_file_descriptor_set(
8288
mut self,
8389
encoded_file_descriptor_set: &'b [u8],
@@ -97,7 +103,8 @@ impl<'b> Builder<'b> {
97103
/// Build a gRPC Reflection Service to be served via Tonic.
98104
pub fn build(mut self) -> Result<ServerReflectionServer<impl ServerReflection>, Error> {
99105
if self.include_reflection_service {
100-
self = self.register_encoded_file_descriptor_set(crate::proto::FILE_DESCRIPTOR_SET);
106+
self =
107+
self.register_encoded_file_descriptor_set(crate::proto::REFLECTION_DESCRIPTOR_SET);
101108
}
102109

103110
for encoded in &self.encoded_file_descriptor_sets {
@@ -304,14 +311,16 @@ struct ReflectionService {
304311

305312
#[tonic::async_trait]
306313
impl ServerReflection for ReflectionService {
307-
type ServerReflectionInfoStream = mpsc::Receiver<Result<ServerReflectionResponse, Status>>;
314+
type ServerReflectionInfoStream = Pin<
315+
Box<dyn Stream<Item = Result<ServerReflectionResponse, Status>> + Send + Sync + 'static>,
316+
>;
308317

309318
async fn server_reflection_info(
310319
&self,
311320
req: Request<Streaming<ServerReflectionRequest>>,
312321
) -> Result<Response<Self::ServerReflectionInfoStream>, Status> {
313322
let mut req_rx = req.into_inner();
314-
let (mut resp_tx, resp_rx) = mpsc::channel::<Result<ServerReflectionResponse, Status>>(1);
323+
let (resp_tx, resp_rx) = mpsc::channel::<Result<ServerReflectionResponse, Status>>(1);
315324

316325
let state = self.state.clone();
317326

@@ -356,6 +365,6 @@ impl ServerReflection for ReflectionService {
356365
}
357366
});
358367

359-
Ok(Response::new(resp_rx))
368+
Ok(Response::new(Box::pin(ReceiverStream::new(resp_rx))))
360369
}
361370
}

0 commit comments

Comments
 (0)