1 use hello_world::greeter_client::GreeterClient;
2 use hello_world::HelloRequest;
3 use service::AuthSvc;
4 use tower::ServiceBuilder;
5
6 use tonic::{transport::Channel, Request, Status};
7
8 pub mod hello_world {
9 tonic::include_proto!("helloworld");
10 }
11
12 #[tokio::main]
main() -> Result<(), Box<dyn std::error::Error>>13 async fn main() -> Result<(), Box<dyn std::error::Error>> {
14 let channel = Channel::from_static("http://[::1]:50051").connect().await?;
15
16 let channel = ServiceBuilder::new()
17 // Interceptors can be also be applied as middleware
18 .layer(tonic::service::InterceptorLayer::new(intercept))
19 .layer_fn(AuthSvc::new)
20 .service(channel);
21
22 let mut client = GreeterClient::new(channel);
23
24 let request = tonic::Request::new(HelloRequest {
25 name: "Tonic".into(),
26 });
27
28 let response = client.say_hello(request).await?;
29
30 println!("RESPONSE={:?}", response);
31
32 Ok(())
33 }
34
35 // An interceptor function.
intercept(req: Request<()>) -> Result<Request<()>, Status>36 fn intercept(req: Request<()>) -> Result<Request<()>, Status> {
37 println!("received {:?}", req);
38 Ok(req)
39 }
40
41 mod service {
42 use http::{Request, Response};
43 use std::future::Future;
44 use std::pin::Pin;
45 use std::task::{Context, Poll};
46 use tonic::body::Body;
47 use tonic::transport::Channel;
48 use tower::Service;
49
50 pub struct AuthSvc {
51 inner: Channel,
52 }
53
54 impl AuthSvc {
new(inner: Channel) -> Self55 pub fn new(inner: Channel) -> Self {
56 AuthSvc { inner }
57 }
58 }
59
60 impl Service<Request<Body>> for AuthSvc {
61 type Response = Response<Body>;
62 type Error = Box<dyn std::error::Error + Send + Sync>;
63 #[allow(clippy::type_complexity)]
64 type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
65
poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>66 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
67 self.inner.poll_ready(cx).map_err(Into::into)
68 }
69
call(&mut self, req: Request<Body>) -> Self::Future70 fn call(&mut self, req: Request<Body>) -> Self::Future {
71 // See: https://docs.rs/tower/latest/tower/trait.Service.html#be-careful-when-cloning-inner-services
72 let clone = self.inner.clone();
73 let mut inner = std::mem::replace(&mut self.inner, clone);
74
75 Box::pin(async move {
76 // Do extra async work here...
77 let response = inner.call(req).await?;
78
79 Ok(response)
80 })
81 }
82 }
83 }
84