1 use tonic::{transport::Server, Code, Request, Response, Status}; 2 use tonic_types::{BadRequest, Help, LocalizedMessage, StatusExt}; 3 4 use hello_world::greeter_server::{Greeter, GreeterServer}; 5 use hello_world::{HelloReply, HelloRequest}; 6 7 pub mod hello_world { 8 tonic::include_proto!("helloworld"); 9 } 10 11 #[derive(Default)] 12 pub struct MyGreeter {} 13 14 #[tonic::async_trait] 15 impl Greeter for MyGreeter { 16 async fn say_hello( 17 &self, 18 request: Request<HelloRequest>, 19 ) -> Result<Response<HelloReply>, Status> { 20 println!("Got a request from {:?}", request.remote_addr()); 21 22 // Extract request data 23 let name = request.into_inner().name; 24 25 // Create empty BadRequest struct 26 let mut bad_request = BadRequest::new(vec![]); 27 28 // Add violations conditionally 29 if name.is_empty() { 30 bad_request.add_violation("name", "name cannot be empty"); 31 } else if name.len() > 20 { 32 bad_request.add_violation("name", "name is too long"); 33 } 34 35 if !bad_request.is_empty() { 36 // Add aditional error details if necessary 37 let help = Help::with_link("description of link", "https://resource.example.local"); 38 39 let localized_message = LocalizedMessage::new("en-US", "message for the user"); 40 41 // Generate error status 42 let status = Status::with_error_details_vec( 43 Code::InvalidArgument, 44 "request contains invalid arguments", 45 vec![bad_request.into(), help.into(), localized_message.into()], 46 ); 47 48 return Err(status); 49 } 50 51 let reply = hello_world::HelloReply { 52 message: format!("Hello {}!", name), 53 }; 54 Ok(Response::new(reply)) 55 } 56 } 57 58 #[tokio::main] 59 async fn main() -> Result<(), Box<dyn std::error::Error>> { 60 let addr = "[::1]:50051".parse().unwrap(); 61 let greeter = MyGreeter::default(); 62 63 println!("GreeterServer listening on {}", addr); 64 65 Server::builder() 66 .add_service(GreeterServer::new(greeter)) 67 .serve(addr) 68 .await?; 69 70 Ok(()) 71 } 72