use crate::{
endpoint::{Handler, HandlerOutput},
middleware::{Middleware, MiddlewareArc, MiddlewareHandler},
request::Request,
router::Router,
server::{state::State, Server},
};
use async_std::sync::{Arc, RwLock, Weak};
pub struct Route<S: State> {
pub(crate) router: Weak<RwLock<Router<S>>>,
pub(crate) path: String,
pub(crate) middleware: MiddlewareArc<S, Request<S>, HandlerOutput>,
pub(crate) prefix: bool,
}
impl<S: State> Route<S> {
pub(crate) fn new(router: Weak<RwLock<Router<S>>>, path: &str) -> Self {
Self {
router,
path: path.to_owned(),
middleware: Arc::new(RwLock::new(vec![])),
prefix: false,
}
}
pub fn at(&mut self, path: &str) -> Route<S> {
let mut p = self.path.clone();
if !p.ends_with('/') && !path.starts_with('/') {
p.push('/');
}
if path != "/" {
p.push_str(path);
}
let router = Weak::clone(&self.router);
Route {
router,
path: p,
middleware: self.middleware.clone(),
prefix: false,
}
}
pub async fn with<M>(&mut self, middleware: M) -> &mut Self
where
M: Middleware<S, Request<S>, HandlerOutput>,
{
log::trace!(
"Adding middleware {} to route {:?}",
middleware.name(),
self.path
);
self.middleware.write().await.push(Arc::new(middleware));
self
}
pub async fn nest<ST: State>(&mut self, service: Server<ST>) -> &mut Self {
let prefix = self.prefix;
self.prefix = true;
self.all(service).await;
self.prefix = prefix;
self
}
pub async fn method(
&mut self,
method: http_types::Method,
ep: impl Handler<Request<S>, HandlerOutput>,
) -> &mut Route<S> {
if self.prefix {
let ep = StripPrefixEndpoint::new(ep);
let wildcard = self.at("*");
let router = Weak::clone(&wildcard.router)
.upgrade()
.expect("router is not accessible");
let middleware = Arc::clone(&wildcard.middleware);
router.write().await.add(
&wildcard.path,
method,
MiddlewareHandler::wrap_with_middleware(ep, middleware).await,
);
} else {
let router = Weak::clone(&self.router)
.upgrade()
.expect("router is not accessible");
let middleware = Arc::clone(&self.middleware);
router.write().await.add(
&self.path,
method,
MiddlewareHandler::wrap_with_middleware(ep, middleware).await,
);
}
self
}
pub async fn all(&mut self, ep: impl Handler<Request<S>, HandlerOutput>) -> &mut Self {
if self.prefix {
let ep = StripPrefixEndpoint::new(ep);
let wildcard = self.at("*");
let router = Weak::clone(&wildcard.router)
.upgrade()
.expect("router is not accessible");
let middleware = Arc::clone(&wildcard.middleware);
router.write().await.add_all(
&wildcard.path,
MiddlewareHandler::wrap_with_middleware(ep, middleware).await,
);
} else {
let router = Weak::clone(&self.router)
.upgrade()
.expect("router is not accessible");
let middleware = Arc::clone(&self.middleware);
router.write().await.add_all(
&self.path,
MiddlewareHandler::wrap_with_middleware(ep, middleware).await,
);
}
self
}
pub async fn get(&mut self, ep: impl Handler<Request<S>, HandlerOutput>) -> &mut Self {
self.method(http_types::Method::Get, ep).await;
self
}
pub async fn head(&mut self, ep: impl Handler<Request<S>, HandlerOutput>) -> &mut Self {
self.method(http_types::Method::Head, ep).await;
self
}
pub async fn put(&mut self, ep: impl Handler<Request<S>, HandlerOutput>) -> &mut Self {
self.method(http_types::Method::Put, ep).await;
self
}
pub async fn post(&mut self, ep: impl Handler<Request<S>, HandlerOutput>) -> &mut Self {
self.method(http_types::Method::Post, ep).await;
self
}
pub async fn delete(&mut self, ep: impl Handler<Request<S>, HandlerOutput>) -> &mut Self {
self.method(http_types::Method::Delete, ep).await;
self
}
pub async fn options(&mut self, ep: impl Handler<Request<S>, HandlerOutput>) -> &mut Self {
self.method(http_types::Method::Options, ep).await;
self
}
pub async fn connect(&mut self, ep: impl Handler<Request<S>, HandlerOutput>) -> &mut Self {
self.method(http_types::Method::Connect, ep).await;
self
}
pub async fn patch(&mut self, ep: impl Handler<Request<S>, HandlerOutput>) -> &mut Self {
self.method(http_types::Method::Patch, ep).await;
self
}
pub async fn trace(&mut self, ep: impl Handler<Request<S>, HandlerOutput>) -> &mut Self {
self.method(http_types::Method::Trace, ep).await;
self
}
}
#[derive(Debug)]
struct StripPrefixEndpoint<E>(Arc<E>);
impl<E> StripPrefixEndpoint<E> {
fn new(ep: E) -> Self {
Self(Arc::new(ep))
}
}
impl<E> Clone for StripPrefixEndpoint<E> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
#[async_trait::async_trait]
impl<S: State, E> Handler<Request<S>, HandlerOutput> for StripPrefixEndpoint<E>
where
E: Handler<Request<S>, HandlerOutput>,
{
async fn call(&self, args: Request<S>) -> HandlerOutput {
let Request {
state,
mut req,
captures,
} = args;
let rest = captures
.iter()
.rev()
.find_map(|captures| captures.wildcard())
.unwrap_or_default();
req.url_mut().set_path(rest);
self.0
.call(Request {
state,
req,
captures,
})
.await
}
}