use std::sync::Arc;
use crate::{Client, Request, ResponseAsync, Result};
mod redirect;
pub use redirect::Redirect;
use async_trait::async_trait;
use futures_util::future::BoxFuture;
#[async_trait]
pub trait Middleware: 'static + Send + Sync {
async fn handle(&self, req: Request, client: Client, next: Next<'_>) -> Result<ResponseAsync>;
}
#[async_trait]
impl<F> Middleware for F
where
F: Send
+ Sync
+ 'static
+ for<'a> Fn(Request, Client, Next<'a>) -> BoxFuture<'a, Result<ResponseAsync>>,
{
async fn handle(&self, req: Request, client: Client, next: Next<'_>) -> Result<ResponseAsync> {
(self)(req, client, next).await
}
}
#[allow(missing_debug_implementations)]
pub struct Next<'a> {
next_middleware: &'a [Arc<dyn Middleware>],
endpoint: &'a (dyn (Fn(Request, Client) -> BoxFuture<'static, Result<ResponseAsync>>)
+ Send
+ Sync
+ 'static),
}
impl Clone for Next<'_> {
fn clone(&self) -> Self {
Self {
next_middleware: self.next_middleware,
endpoint: self.endpoint,
}
}
}
impl Copy for Next<'_> {}
impl<'a> Next<'a> {
pub fn new(
next: &'a [Arc<dyn Middleware>],
endpoint: &'a (dyn (Fn(Request, Client) -> BoxFuture<'static, Result<ResponseAsync>>)
+ Send
+ Sync
+ 'static),
) -> Self {
Self {
endpoint,
next_middleware: next,
}
}
pub fn run(mut self, req: Request, client: Client) -> BoxFuture<'a, Result<ResponseAsync>> {
if let Some((current, next)) = self.next_middleware.split_first() {
self.next_middleware = next;
current.handle(req, client, self)
} else {
(self.endpoint)(req, client)
}
}
}