Tonic Async Interceptor

This crate contains AsyncInterceptor, an async variant of Tonic's Interceptor. Other than accepting an async interceptor function, it works the same as Interceptor.

Async interceptor functions are useful for tasks like authentication, where you need to make asynchronous calls to another service or database within the interceptor.

Usage

Using with Tonic built-in Server/Router

```rust async fn myasyncinterceptor(req: Request<()>) -> Result { // do things and stuff Ok(req) }

async fn main() { use tonic::transport::server; use tonicasyncinterceptor::asyncinterceptor; let router = server::Server::builder() .layer(asyncinterceptor(myasyncinterceptor)) .addservice(someservice) .addservice(anotherservice); // ... } ```

Setting a custom extension

Here's an example of an async interceptor which authenticates a user and sets a custom extension for the underlying service to use.

```rust // Your custom extension struct UserContext { user_id: String, }

// Async interceptor fn async fn authenticate(req: Request<()>) -> Result { // Inspect the gRPC metadata. let authheaderval = match req.metadata().get("x-my-auth-header") { Some(val) => val, None => return Err(Status::unauthorized("Request missing creds")), }; // Call some async function (verify_auth). let maybeuserid: Result = verifyauth(authheader_val).await;

let user_id = match maybe_user_id {
    Ok(id) => id,
    Err(_) => return Err(Status::unauthorized("Invalid creds")),
};

// Insert an extension, which can be inspected by the service.
req.extensions_mut().insert(UserContext { user_id });

Ok(req)

} ```

Why is this a separate crate?

The code in this crate was originally intended to live in the official Tonic crate, alongside the non-async interceptor code. However, the maintainer decided not to merge it due to lack of time and misalignment with his future vision for Tonic.