use crate::{handler::Handler, regex::Rule, request::Request, response::Response, Result};
use async_recursion::async_recursion;
use async_trait::async_trait;
use std::{future::Future, sync::Arc};
#[async_trait]
pub trait Middleware: Send + Sync + 'static {
#[must_use]
async fn hook(&self, req: Request, next: Next) -> Result<Response>;
}
#[async_trait]
impl<F, Fut> Middleware for F
where
Fut: Future<Output = Result<Response>> + 'static + Send,
F: Send + Sync + 'static + Fn(Request, Next) -> Fut,
{
async fn hook(&self, req: Request, next: Next) -> Result<Response> {
self(req, next).await
}
}
#[derive(Clone)]
pub struct Next {
pub(crate) path: String,
pub(crate) middleware: Vec<(Rule, Arc<dyn Middleware>)>,
pub(crate) handler: Arc<dyn Handler>,
}
impl Next {
#[inline]
#[async_recursion]
pub async fn next(self, req: Request) -> Result<Response> {
match self.middleware.split_first() {
Some((head, middleware)) => {
let next = Next {
path: self.path,
handler: self.handler.clone(),
middleware: middleware.to_vec(),
};
let (rule, mid) = head;
if rule.validate_path(&next.path) {
mid.hook(req, next).await
} else {
next.next(req).await
}
}
None => self.handler.handle(req).await,
}
}
}