#[doc(inline)]
pub use crate::http_client::{Body, HttpClient, Request, Response};
pub mod logger;
use crate::Exception;
use futures::future::BoxFuture;
use std::sync::Arc;
pub trait Middleware<C: HttpClient>: 'static + Send + Sync {
fn handle<'a>(
&'a self,
req: Request,
client: C,
next: Next<'a, C>,
) -> BoxFuture<'a, Result<Response, Exception>>;
}
impl<F, C: HttpClient> Middleware<C> for F
where
F: Send
+ Sync
+ 'static
+ for<'a> Fn(Request, C, Next<'a, C>) -> BoxFuture<'a, Result<Response, Exception>>,
{
fn handle<'a>(
&'a self,
req: Request,
client: C,
next: Next<'a, C>,
) -> BoxFuture<'a, Result<Response, Exception>> {
(self)(req, client, next)
}
}
#[allow(missing_debug_implementations)]
pub struct Next<'a, C: HttpClient> {
next_middleware: &'a [Arc<dyn Middleware<C>>],
endpoint: &'a (dyn (Fn(Request, C) -> BoxFuture<'static, Result<Response, Exception>>)
+ 'static
+ Send
+ Sync),
}
impl<C: HttpClient> Clone for Next<'_, C> {
fn clone(&self) -> Self {
Self {
next_middleware: self.next_middleware,
endpoint: self.endpoint,
}
}
}
impl<C: HttpClient> Copy for Next<'_, C> {}
impl<'a, C: HttpClient> Next<'a, C> {
pub fn new(
next: &'a [Arc<dyn Middleware<C>>],
endpoint: &'a (dyn (Fn(Request, C) -> BoxFuture<'static, Result<Response, Exception>>)
+ 'static
+ Send
+ Sync),
) -> Self {
Self {
endpoint,
next_middleware: next,
}
}
pub fn run(mut self, req: Request, client: C) -> BoxFuture<'a, Result<Response, Exception>> {
if let Some((current, next)) = self.next_middleware.split_first() {
self.next_middleware = next;
current.handle(req, client, self)
} else {
(self.endpoint)(req, client)
}
}
}