xref: /tonic/examples/src/mock/mock.rs (revision 66aaa5bb)
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