use axum::{Router, extract::Request, response::IntoResponse, routing::Route};
use std::convert::Infallible;
use tower::{Layer, Service};
type LayerFn<S> = Box<dyn Fn(Router<S>) -> Router<S> + Send + Sync>;
pub struct LayerStack<S> {
layers: Vec<LayerFn<S>>,
}
impl<S> LayerStack<S>
where
S: Clone + Send + Sync + 'static,
{
pub fn new() -> Self {
Self { layers: Vec::new() }
}
pub fn push<L>(&mut self, layer: L)
where
L: Layer<Route> + Clone + Send + Sync + 'static,
L::Service: Service<Request> + Clone + Send + Sync + 'static,
<L::Service as Service<Request>>::Response: IntoResponse + 'static,
<L::Service as Service<Request>>::Error: Into<Infallible> + 'static,
<L::Service as Service<Request>>::Future: Send + 'static,
{
self.layers.push(Box::new(move |router: Router<S>| {
router.layer(layer.clone())
}));
}
pub fn apply(&self, mut router: Router<S>) -> Router<S> {
for layer_fn in self.layers.iter() {
router = layer_fn(router);
}
router
}
}
impl<S> Default for LayerStack<S>
where
S: Clone + Send + Sync + 'static,
{
fn default() -> Self {
Self::new()
}
}