use async_std::task::block_on;
use crate::{
request::Request,
response::Response,
router::{middleware::register, next::Next, route::Route},
utils::url::join_url,
ws::Ws
};
pub(crate) mod resolver;
pub(crate) mod middleware;
pub(crate) mod routes;
pub mod route;
pub mod next;
pub(crate) type Middleware = dyn for<'a> Fn(&'a mut Request, &'a mut Response, &'a mut Next) -> &'a mut Response + Send + Sync + 'static;
pub(crate) type WebRoute = dyn for<'a> Fn(&'a mut Request, &'a mut Response) -> &'a mut Response + Send + Sync + 'static;
pub(crate) type WsRoute = dyn for<'a> Fn(&'a mut Request, &'a mut Ws) + Send + Sync + 'static;
pub(crate) type Group = for<'a> fn(&mut Router);
pub struct Router {
pub(crate) web: Vec<Route<WebRoute>>,
pub(crate) ws: Vec<Box<Route<WsRoute>>>,
pub(crate) subdomain: Vec<String>,
pub(crate) path: String,
pub(crate) middlewares: Vec<String>,
pub(crate) group: Option<Group>,
pub(crate) routers: Vec<Box<Router>>,
pub(crate) route_not_found_callback: Option<Box<WebRoute>>,
}
impl Router {
pub fn get<C>(&mut self, path: &str, callback: C) -> &mut Route<WebRoute>
where
C: for<'a> AsyncFn(&'a mut Request, &'a mut Response) -> &'a mut Response + Send + Sync + 'static,
{
return self.route("GET", path, callback);
}
pub fn post<C>(&mut self, path: &str, callback: C) -> &mut Route<WebRoute>
where
C: for<'a> AsyncFn(&'a mut Request, &'a mut Response) -> &'a mut Response + Send + Sync + 'static,
{
return self.route("POST", path, callback);
}
pub fn put<C>(&mut self, path: &str, callback: C) -> &mut Route<WebRoute>
where
C: for<'a> AsyncFn(&'a mut Request, &'a mut Response) -> &'a mut Response + Send + Sync + 'static,
{
return self.route("PUT", path, callback);
}
pub fn patch<C>(&mut self, path: &str, callback: C) -> &mut Route<WebRoute>
where
C: for<'a> AsyncFn(&'a mut Request, &'a mut Response) -> &'a mut Response + Send + Sync + 'static,
{
return self.route("PATCH", path, callback);
}
pub fn delete<C>(&mut self, path: &str, callback: C) -> &mut Route<WebRoute>
where
C: for<'a> AsyncFn(&'a mut Request, &'a mut Response) -> &'a mut Response + Send + Sync + 'static,
{
return self.route("DELETE", path, callback);
}
pub fn head<C>(&mut self, path: &str, callback: C) -> &mut Route<WebRoute>
where
C: for<'a> AsyncFn(&'a mut Request, &'a mut Response) -> &'a mut Response + Send + Sync + 'static,
{
return self.route("HEAD", path, callback);
}
pub fn options<C>(&mut self, path: &str, callback: C) -> &mut Route<WebRoute>
where
C: for<'a> AsyncFn(&'a mut Request, &'a mut Response) -> &'a mut Response + Send + Sync + 'static,
{
return self.route("OPTIONS", path, callback);
}
pub fn route<C>(&mut self, method: &str, path: &str, callback: C) -> &mut Route<WebRoute>
where
C: for<'a> AsyncFn(&'a mut Request, &'a mut Response) -> &'a mut Response + Send + Sync + 'static
{
let idx = self.web.len();
self.web.push(Route {
subdomain: self.subdomain.clone().join("."),
method: String::from(method.to_uppercase()),
path: join_url(vec![self.path.clone(), String::from(path)]),
handler: Box::new(move |req, res| block_on(callback(req, res))),
middlewares: self.middlewares.clone()
});
return &mut self.web[idx];
}
pub fn ws<C>(&mut self, path: &str, callback: C) -> &mut Route<WsRoute>
where
C: for<'a> AsyncFn(&'a mut Request, &'a mut Ws) + Send + Sync + 'static
{
let idx = self.ws.len();
self.ws.push(Box::new(Route {
subdomain: self.subdomain.clone().join("."),
method: String::from("GET"),
path: join_url(vec![self.path.clone(), String::from(path)]),
handler: Box::new(move |req, ws| block_on(callback(req, ws))),
middlewares: vec![],
}));
return &mut self.ws[idx];
}
pub fn not_found<C>(&mut self, callback: C)
where
C: for<'a> AsyncFn(&'a mut Request, &'a mut Response) -> &'a mut Response + Send + Sync + 'static,
{
self.route_not_found_callback = Some(Box::new(move |req, res| block_on(callback(req, res))));
}
pub fn middleware<C>(&mut self, callback: C) -> &mut Self
where
C: for<'a> AsyncFn(&'a mut Request, &'a mut Response, &'a mut Next) -> &'a mut Response + Send + Sync + 'static
{
self.middlewares
.push(register(Box::new(move |req, res, next| block_on(callback(req, res, next)))));
return self;
}
pub fn group<'g>(&'g mut self, path: &str, group: Group) -> GroupRouter<'g> {
let idx = self.routers.len();
self.routers.push(Box::new(Router {
web: Vec::new(),
ws: Vec::new(),
subdomain: self.subdomain.clone(),
path: join_url(vec![self.path.clone(), String::from(path)]),
middlewares: self.middlewares.clone(),
group: Some(group),
routers: vec![],
route_not_found_callback: None
}));
return GroupRouter::new(self.routers[idx].as_mut());
}
pub fn subdomain<'g>(&'g mut self, domain: &str, group: Group) -> GroupRouter<'g> {
let sub_group = self.group("/", group);
sub_group.router.subdomain.extend(domain.split(".").map(|v| v.to_string()).collect::<Vec<_>>());
return sub_group;
}
}
pub struct GroupRouter<'g> {
router: &'g mut Router
}
impl <'g>GroupRouter<'g> {
pub(crate) fn new(router: &'g mut Router) -> Self {
return Self {
router: router
};
}
pub fn middleware<C>(&mut self, callback: C) -> &mut Self
where
C: for<'a> AsyncFn(&'a mut Request, &'a mut Response, &'a mut Next) -> &'a mut Response + Send + Sync + 'static
{
self.router.middleware(callback);
return self;
}
}