1 use hyper_util::rt::TokioIo;
2 use tonic::{
3 transport::{Endpoint, Server, Uri},
4 Request, Response, Status,
5 };
6 use tower::service_fn;
7
8 pub mod hello_world {
9 tonic::include_proto!("helloworld");
10 }
11
12 use hello_world::{
13 greeter_client::GreeterClient,
14 greeter_server::{Greeter, GreeterServer},
15 HelloReply, HelloRequest,
16 };
17
18 #[tokio::main]
main() -> Result<(), Box<dyn std::error::Error>>19 async fn main() -> Result<(), Box<dyn std::error::Error>> {
20 let (client, server) = tokio::io::duplex(1024);
21
22 let greeter = MyGreeter::default();
23
24 tokio::spawn(async move {
25 Server::builder()
26 .add_service(GreeterServer::new(greeter))
27 .serve_with_incoming(tokio_stream::once(Ok::<_, std::io::Error>(server)))
28 .await
29 });
30
31 // Move client to an option so we can _move_ the inner value
32 // on the first attempt to connect. All other attempts will fail.
33 let mut client = Some(client);
34 let channel = Endpoint::try_from("http://[::]:50051")?
35 .connect_with_connector(service_fn(move |_: Uri| {
36 let client = client.take();
37
38 async move {
39 if let Some(client) = client {
40 Ok(TokioIo::new(client))
41 } else {
42 Err(std::io::Error::other("Client already taken"))
43 }
44 }
45 }))
46 .await?;
47
48 let mut client = GreeterClient::new(channel);
49
50 let request = tonic::Request::new(HelloRequest {
51 name: "Tonic".into(),
52 });
53
54 let response = client.say_hello(request).await?;
55
56 println!("RESPONSE={:?}", response);
57
58 Ok(())
59 }
60
61 #[derive(Default)]
62 pub struct MyGreeter {}
63
64 #[tonic::async_trait]
65 impl Greeter for MyGreeter {
say_hello( &self, request: Request<HelloRequest>, ) -> Result<Response<HelloReply>, Status>66 async fn say_hello(
67 &self,
68 request: Request<HelloRequest>,
69 ) -> Result<Response<HelloReply>, Status> {
70 println!("Got a request: {:?}", request);
71
72 let reply = hello_world::HelloReply {
73 message: format!("Hello {}!", request.into_inner().name),
74 };
75 Ok(Response::new(reply))
76 }
77 }
78