use axum::{Router, response::IntoResponse};
pub use axum::{extract::Request, middleware::Next, response::Response};
use std::future::Future;
pub fn apply<F, Fut, R>(router: Router, middleware: F) -> Router
where
F: Fn(Request, Next) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = R> + Send + 'static,
R: IntoResponse + 'static,
{
router.layer(axum::middleware::from_fn(
move |request: Request, next: Next| {
let middleware = middleware.clone();
async move { middleware(request, next).await }
},
))
}
#[doc(hidden)]
pub fn apply_routes<F, Fut, R>(router: Router, middleware: F) -> Router
where
F: Fn(Request, Next) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = R> + Send + 'static,
R: IntoResponse + 'static,
{
router.route_layer(axum::middleware::from_fn(
move |request: Request, next: Next| {
let middleware = middleware.clone();
async move { middleware(request, next).await }
},
))
}
pub struct Application {
router: Router,
middleware: Vec<Box<dyn FnOnce(Router) -> Router + Send>>,
}
impl Application {
pub fn new(router: Router) -> Self {
Self {
router,
middleware: Vec::new(),
}
}
pub fn use_middleware<F, Fut, R>(mut self, middleware: F) -> Self
where
F: Fn(Request, Next) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = R> + Send + 'static,
R: IntoResponse + 'static,
{
self.middleware
.push(Box::new(move |router| apply(router, middleware)));
self
}
pub fn into_router(self) -> Router {
self.middleware
.into_iter()
.rev()
.fold(self.router, |router, wrap| wrap(router))
}
}