mod header;
mod revalidate;
use std::fmt;
use std::future::Future;
use std::sync::Arc;
use futures::future::BoxFuture;
pub use header::SetHeader;
pub use revalidate::{InMemValidators, Revalidate, Validator, Validators};
use crate::context::Context;
use crate::worker::{IntoOutcome, Outcome, Worker};
pub trait Middleware<C>: Send + Sync + 'static {
fn handle(&self, cx: Context<C>, next: Next<C>) -> impl Future<Output = Outcome> + Send;
}
pub struct Next<C> {
worker: Arc<dyn ErasedWorker<C>>,
}
impl<C> Next<C> {
pub async fn run(self, cx: Context<C>) -> Outcome
where
C: Send + 'static,
{
self.worker.handle(cx).await
}
}
impl<C> fmt::Debug for Next<C> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Next").finish_non_exhaustive()
}
}
trait ErasedWorker<C>: Send + Sync + 'static {
fn handle(&self, cx: Context<C>) -> BoxFuture<'_, Outcome>;
}
impl<C: Send + 'static, W: Worker<C>> ErasedWorker<C> for W {
fn handle(&self, cx: Context<C>) -> BoxFuture<'_, Outcome> {
Box::pin(Worker::handle(self, cx))
}
}
pub trait WorkerExt: Sized {
fn layer<C, M>(self, middleware: M) -> Layered<M, C>
where
C: Send + 'static,
Self: Worker<C>,
M: Middleware<C>,
{
Layered {
middleware,
worker: Arc::new(self),
}
}
}
impl<W> WorkerExt for W {}
pub struct Layered<M, C> {
middleware: M,
worker: Arc<dyn ErasedWorker<C>>,
}
impl<M, C> Worker<C> for Layered<M, C>
where
M: Middleware<C>,
C: Send + 'static,
{
fn handle(&self, cx: Context<C>) -> impl Future<Output = Outcome> + Send {
let next = Next {
worker: Arc::clone(&self.worker),
};
self.middleware.handle(cx, next)
}
}
impl<M: Clone, C> Clone for Layered<M, C> {
fn clone(&self) -> Self {
Self {
middleware: self.middleware.clone(),
worker: Arc::clone(&self.worker),
}
}
}
impl<M: fmt::Debug, C> fmt::Debug for Layered<M, C> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Layered")
.field("middleware", &self.middleware)
.finish_non_exhaustive()
}
}
pub const fn from_fn<F>(f: F) -> FromFn<F> {
FromFn(f)
}
#[derive(Clone, Copy)]
pub struct FromFn<F>(F);
impl<C, F, Fut> Middleware<C> for FromFn<F>
where
C: Send + 'static,
F: Fn(Context<C>, Next<C>) -> Fut + Send + Sync + 'static,
Fut: Future<Output: IntoOutcome> + Send,
{
fn handle(&self, cx: Context<C>, next: Next<C>) -> impl Future<Output = Outcome> + Send {
let future = (self.0)(cx, next);
async move { future.await.into_outcome() }
}
}
impl<F> fmt::Debug for FromFn<F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FromFn").finish_non_exhaustive()
}
}
#[cfg(test)]
mod tests;