hyperium / tonic

A native gRPC client & server implementation with async/await support.
https://docs.rs/tonic
MIT License
10.09k stars 1.02k forks source link

[question] how to set header when a request leaves the grpc server #2056

Open liubocflt opened 1 week ago

liubocflt commented 1 week ago

Hi devs,

Thanks a lot for developing tonic for rust grpc.

I'm looking for a solution of tonic to set header in an interceptor when a request leaves the grpc server, is there a helper for this to do so?

In golang, it can be written as

func fooInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
    startTime := time.Now()
    err := handler(ctx, req)
    // elapsedTime := time.Since(startTime).Nanoseconds()
    // set header
    return err
}
imotai commented 1 week ago

Maybe the following answer can help you.

  1. add the meta to the response
    
    use tonic::{Request, Response, Status};
    use std::time::Instant;

async fn foo_interceptor( mut req: Request, next: tonic::service::Interceptor, ) -> Result<Response, Status> { let start = Instant::now();

// Handle the request
let mut response = next.call(req).await?;

// Add custom headers to response
response.metadata_mut()
    .insert("x-elapsed-time", elapsed.as_nanos().to_string().parse().unwrap());

Ok(response)

}


2. add the inteceptor to the server

```rust
Server::builder()
    .add_service(
        ServiceBuilder::new()
            .intercept(foo_interceptor)
            .service(your_service)
    )
    .serve(addr)
    .await?;
liubocflt commented 6 days ago

@imotai Thanks for your suggestions, unfortunately, I was not able to make it work with next: tonic::service::Interceptor.

I did it successfully with the example here, It's cumbersome to do it this way though. https://github.com/hyperium/tonic/blob/master/examples/src/tower/server.rs