use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use http::HeaderMap;
use super::GrpcStatus;
use crate::types::Request;
use crate::types::Response;
pub trait GrpcInterceptor: Send + Sync + 'static {
fn intercept(
&self,
metadata: &mut HeaderMap,
method: &str,
) -> Pin<Box<dyn Future<Output = Result<(), GrpcStatus>> + Send + '_>>;
}
#[derive(Default, Clone)]
pub struct InterceptorChain {
inner: Vec<Arc<dyn GrpcInterceptor>>,
}
impl InterceptorChain {
pub fn new() -> Self {
Self::default()
}
pub fn push<I: GrpcInterceptor + 'static>(mut self, interceptor: I) -> Self {
self.inner.push(Arc::new(interceptor));
self
}
pub async fn run(&self, metadata: &mut HeaderMap, method: &str) -> Result<(), GrpcStatus> {
for ic in &self.inner {
ic.intercept(metadata, method).await?;
}
Ok(())
}
}
pub async fn run_chain(
chain: &InterceptorChain,
req: &mut Request,
method: &str,
) -> Result<(), Response> {
let metadata = req.headers_mut();
match chain.run(metadata, method).await {
Ok(()) => Ok(()),
Err(status) => Err(super::build_grpc_error_response(
status.code,
status.message.as_deref().unwrap_or(""),
)),
}
}