use axum::Router;
use axum::handler::Handler;
use axum::routing::{get, post, put, delete};
type RouteEntry = Box<dyn FnOnce(Router) -> Router + Send>;
pub struct AlunRouter {
builders: Vec<RouteEntry>,
}
impl AlunRouter {
pub fn new() -> Self {
Self {
builders: Vec::new(),
}
}
pub fn add_get<H, T>(&mut self, path: &str, handler: H)
where
H: Handler<T, ()>,
T: 'static,
{
let path = path.to_string();
self.builders.push(Box::new(move |r| r.route(&path, get(handler))));
}
pub fn add_post<H, T>(&mut self, path: &str, handler: H)
where
H: Handler<T, ()>,
T: 'static,
{
let path = path.to_string();
self.builders.push(Box::new(move |r| r.route(&path, post(handler))));
}
pub fn add_put<H, T>(&mut self, path: &str, handler: H)
where
H: Handler<T, ()>,
T: 'static,
{
let path = path.to_string();
self.builders.push(Box::new(move |r| r.route(&path, put(handler))));
}
pub fn add_delete<H, T>(&mut self, path: &str, handler: H)
where
H: Handler<T, ()>,
T: 'static,
{
let path = path.to_string();
self.builders.push(Box::new(move |r| r.route(&path, delete(handler))));
}
pub fn add_route<H, T>(&mut self, method: &str, path: &str, handler: H)
where
H: Handler<T, ()>,
T: 'static,
{
let path = path.to_string();
let method = method.to_uppercase();
self.builders.push(Box::new(move |r| {
let router = match method.as_str() {
"GET" => get(handler),
"POST" => post(handler),
"PUT" => put(handler),
"DELETE" => delete(handler),
_ => axum::routing::any(handler),
};
r.route(&path, router)
}));
}
pub fn add_get_with_layer<H, T>(
&mut self, path: &str, handler: H,
wrap: impl FnOnce(axum::routing::MethodRouter<()>) -> axum::routing::MethodRouter<()> + Send + 'static,
)
where
H: Handler<T, ()>,
T: 'static,
{
let path = path.to_string();
self.builders.push(Box::new(move |r| {
let mr = get(handler);
let mr = wrap(mr);
r.route(&path, mr)
}));
}
pub fn add_post_with_layer<H, T>(
&mut self, path: &str, handler: H,
wrap: impl FnOnce(axum::routing::MethodRouter<()>) -> axum::routing::MethodRouter<()> + Send + 'static,
)
where
H: Handler<T, ()>,
T: 'static,
{
let path = path.to_string();
self.builders.push(Box::new(move |r| {
let mr = post(handler);
let mr = wrap(mr);
r.route(&path, mr)
}));
}
pub fn add_put_with_layer<H, T>(
&mut self, path: &str, handler: H,
wrap: impl FnOnce(axum::routing::MethodRouter<()>) -> axum::routing::MethodRouter<()> + Send + 'static,
)
where
H: Handler<T, ()>,
T: 'static,
{
let path = path.to_string();
self.builders.push(Box::new(move |r| {
let mr = put(handler);
let mr = wrap(mr);
r.route(&path, mr)
}));
}
pub fn add_delete_with_layer<H, T>(
&mut self, path: &str, handler: H,
wrap: impl FnOnce(axum::routing::MethodRouter<()>) -> axum::routing::MethodRouter<()> + Send + 'static,
)
where
H: Handler<T, ()>,
T: 'static,
{
let path = path.to_string();
self.builders.push(Box::new(move |r| {
let mr = delete(handler);
let mr = wrap(mr);
r.route(&path, mr)
}));
}
pub fn merge(&mut self, prefix: &str, sub: AlunRouter) {
let prefix = prefix.to_string();
self.builders.push(Box::new(move |r| r.nest(&prefix, sub.into_axum())));
}
pub fn into_axum(self) -> Router {
self.builders
.into_iter()
.fold(Router::new(), |r, f| f(r))
}
}
impl Default for AlunRouter {
fn default() -> Self {
Self::new()
}
}