Skip to content

Interceptors in gRPC Controllers ​

Sword lets you apply interceptors to gRPC controllers to validate or transform the incoming metadata of remote calls.

Traditional interceptors ​

The OnRequest Trait ​

In gRPC, OnRequest lets you intercept the request before it reaches the service method.

rust
use sword::grpc::*;
use sword::prelude::*;

#[derive(Interceptor)]
struct AuthInterceptor;

impl OnRequest for AuthInterceptor {
    async fn on_request(&self, req: Request<()>) -> GrpcInterceptorResult {
        if req.metadata().get("authorization").is_none() {
            return Err(Status::unauthenticated("missing authorization metadata"));
        }

        Ok(req)
    }
}
rust
use sword::prelude::*;

#[controller(kind = Controller::Grpc, service = proto::user_service_server::UserServiceServer)]
#[interceptor(AuthInterceptor)]
struct UsersController;

No next()

Unlike web interceptors, there is no next() in this variant: the interceptor validates/transforms the incoming metadata and returns Ok(req) or an error Status.

Interceptors with configuration ​

The OnRequestWithConfig Trait ​

In gRPC you can use OnRequestWithConfig<T> to inject configuration parameters into the validation/interception.

rust
use sword::grpc::*;
use sword::prelude::*;

#[derive(Interceptor)]
struct ApiKeyInterceptor;

impl OnRequestWithConfig<&'static str> for ApiKeyInterceptor {
    async fn on_request(
        &self,
        expected_key: &'static str,
        req: Request<()>,
    ) -> GrpcInterceptorResult {
        let Some(value) = req.metadata().get("x-api-key") else {
            return Err(Status::unauthenticated("missing x-api-key"));
        };

        let Ok(value) = value.to_str() else {
            return Err(Status::unauthenticated("invalid x-api-key"));
        };

        if value != expected_key {
            return Err(Status::permission_denied("invalid x-api-key"));
        }

        Ok(req)
    }
}
rust
use sword::prelude::*;

#[controller(kind = Controller::Grpc, service = proto::user_service_server::UserServiceServer)]
#[interceptor(ApiKeyInterceptor, config = "dev-key")]
struct UsersController;