use crate::{Request, Response, Result};
use async_trait::async_trait;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
pub type BoxedHandler = Arc<
dyn Fn(Request) -> Pin<Box<dyn Future<Output = Result<Response>> + Send>>
+ Send
+ Sync
+ 'static,
>;
pub trait Handler: Send + Sync + 'static {
fn handle(&self, req: Request) -> Pin<Box<dyn Future<Output = Result<Response>> + Send + 'static>>;
}
impl<F, Fut> Handler for F
where
F: Fn(Request) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Result<Response>> + Send + 'static,
{
fn handle(&self, req: Request) -> Pin<Box<dyn Future<Output = Result<Response>> + Send + 'static>> {
Box::pin(self(req))
}
}
#[async_trait]
pub trait Middleware: Send + Sync + 'static {
async fn handle(&self, req: Request, next: Next) -> Result<Response>;
}
pub struct Next {
middleware_stack: Vec<Arc<dyn Middleware>>,
handler: Option<BoxedHandler>,
index: usize,
}
impl Next {
pub fn new(
middleware_stack: Vec<Arc<dyn Middleware>>,
handler: Option<BoxedHandler>,
) -> Self {
Self {
middleware_stack,
handler,
index: 0,
}
}
fn at_index(
middleware_stack: Vec<Arc<dyn Middleware>>,
handler: Option<BoxedHandler>,
index: usize,
) -> Self {
Self {
middleware_stack,
handler,
index,
}
}
pub async fn run(self, req: Request) -> Result<Response> {
if self.index < self.middleware_stack.len() {
let middleware = self.middleware_stack[self.index].clone();
let next = Next::at_index(
self.middleware_stack,
self.handler,
self.index + 1,
);
middleware.handle(req, next).await
} else if let Some(handler) = self.handler {
handler(req).await
} else {
Err(crate::Error::RouteNotFound)
}
}
}
pub async fn execute_middleware_stack(
middleware: Vec<Arc<dyn Middleware>>,
handler: BoxedHandler,
req: Request,
) -> Result<Response> {
let next = Next::new(middleware, Some(handler));
next.run(req).await
}