use std::sync::Arc;
use poem::{Endpoint, IntoResponse, Request, Response, Result};
use crate::Guard;
use crate::dispatch::denial_to_http_response;
pub struct GuardEndpoint<E, G: ?Sized> {
inner: E,
guard: Arc<G>,
}
impl<E, G: ?Sized> GuardEndpoint<E, G> {
pub fn new(inner: E, guard: Arc<G>) -> Self {
Self { inner, guard }
}
}
impl<E, G> Endpoint for GuardEndpoint<E, G>
where
E: Endpoint + Send + Sync,
E::Output: IntoResponse,
G: Guard + ?Sized,
{
type Output = Response;
async fn call(&self, mut req: Request) -> Result<Self::Output> {
match self.guard.check_http(&mut req).await {
Ok(()) => self.inner.call(req).await.map(IntoResponse::into_response),
Err(denial) => Ok(denial_to_http_response(denial)),
}
}
}
pub trait GuardExt: Endpoint + Sized + Send + Sync
where
Self::Output: IntoResponse,
{
fn guard<G>(self, guard: Arc<G>) -> GuardEndpoint<Self, G>
where
G: Guard + ?Sized,
{
GuardEndpoint::new(self, guard)
}
}
impl<E> GuardExt for E
where
E: Endpoint + Send + Sync,
E::Output: IntoResponse,
{
}