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] 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::interceptor(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. 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::BoxBody; 47 use tonic::transport::Body; 48 use tonic::transport::Channel; 49 use tower::Service; 50 51 pub struct AuthSvc { 52 inner: Channel, 53 } 54 55 impl AuthSvc { 56 pub fn new(inner: Channel) -> Self { 57 AuthSvc { inner } 58 } 59 } 60 61 impl Service<Request<BoxBody>> for AuthSvc { 62 type Response = Response<Body>; 63 type Error = Box<dyn std::error::Error + Send + Sync>; 64 #[allow(clippy::type_complexity)] 65 type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>; 66 67 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { 68 self.inner.poll_ready(cx).map_err(Into::into) 69 } 70 71 fn call(&mut self, req: Request<BoxBody>) -> Self::Future { 72 // This is necessary because tonic internally uses `tower::buffer::Buffer`. 73 // See https://github.com/tower-rs/tower/issues/547#issuecomment-767629149 74 // for details on why this is necessary 75 let clone = self.inner.clone(); 76 let mut inner = std::mem::replace(&mut self.inner, clone); 77 78 Box::pin(async move { 79 // Do extra async work here... 80 let response = inner.call(req).await?; 81 82 Ok(response) 83 }) 84 } 85 } 86 } 87