1 use hyper::{Body, Request as HyperRequest, Response as HyperResponse}; 2 use std::task::{Context, Poll}; 3 use tonic::{ 4 body::BoxBody, 5 transport::{NamedService, Server}, 6 Request, Response, Status, 7 }; 8 use tower::Service; 9 10 use hello_world::greeter_server::{Greeter, GreeterServer}; 11 use hello_world::{HelloReply, HelloRequest}; 12 13 pub mod hello_world { 14 tonic::include_proto!("helloworld"); 15 } 16 17 #[derive(Default)] 18 pub struct MyGreeter {} 19 20 #[tonic::async_trait] 21 impl Greeter for MyGreeter { 22 async fn say_hello( 23 &self, 24 request: Request<HelloRequest>, 25 ) -> Result<Response<HelloReply>, Status> { 26 println!("Got a request from {:?}", request.remote_addr()); 27 28 let reply = hello_world::HelloReply { 29 message: format!("Hello {}!", request.into_inner().name), 30 }; 31 Ok(Response::new(reply)) 32 } 33 } 34 35 #[tokio::main] 36 async fn main() -> Result<(), Box<dyn std::error::Error>> { 37 let addr = "[::1]:50051".parse().unwrap(); 38 let greeter = MyGreeter::default(); 39 40 println!("GreeterServer listening on {}", addr); 41 42 let svc = InterceptedService { 43 inner: GreeterServer::new(greeter), 44 }; 45 46 Server::builder().add_service(svc).serve(addr).await?; 47 48 Ok(()) 49 } 50 51 #[derive(Debug, Clone)] 52 struct InterceptedService<S> { 53 inner: S, 54 } 55 56 impl<S> Service<HyperRequest<Body>> for InterceptedService<S> 57 where 58 S: Service<HyperRequest<Body>, Response = HyperResponse<BoxBody>> 59 + NamedService 60 + Clone 61 + Send 62 + 'static, 63 S::Future: Send + 'static, 64 { 65 type Response = S::Response; 66 type Error = S::Error; 67 type Future = futures::future::BoxFuture<'static, Result<Self::Response, Self::Error>>; 68 69 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { 70 self.inner.poll_ready(cx) 71 } 72 73 fn call(&mut self, req: HyperRequest<Body>) -> Self::Future { 74 let mut svc = self.inner.clone(); 75 76 Box::pin(async move { 77 // Do async work here.... 78 79 svc.call(req).await 80 }) 81 } 82 } 83 84 impl<S: NamedService> NamedService for InterceptedService<S> { 85 const NAME: &'static str = S::NAME; 86 } 87