Files
continuwuity/src/api/router/handler.rs
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

81 lines
2.3 KiB
Rust
Raw Normal View History

use axum::{
Router,
extract::FromRequestParts,
response::IntoResponse,
routing::{MethodFilter, on},
};
2024-12-14 21:58:01 -05:00
use conduwuit::Result;
2024-08-08 17:18:30 +00:00
use futures::{Future, TryFutureExt};
use http::Method;
use ruma::api::IncomingRequest;
2024-07-15 03:56:27 +00:00
use super::{Ruma, RumaResponse, State};
2024-08-08 17:18:30 +00:00
pub(in super::super) trait RumaHandler<T> {
fn add_route(&'static self, router: Router<State>, path: &str) -> Router<State>;
fn add_routes(&'static self, router: Router<State>) -> Router<State>;
}
pub(in super::super) trait RouterExt {
2024-08-08 17:18:30 +00:00
fn ruma_route<H, T>(self, handler: &'static H) -> Self
where
H: RumaHandler<T>;
}
2024-07-15 03:56:27 +00:00
impl RouterExt for Router<State> {
2024-08-08 17:18:30 +00:00
fn ruma_route<H, T>(self, handler: &'static H) -> Self
where
H: RumaHandler<T>,
{
handler.add_routes(self)
}
}
macro_rules! ruma_handler {
( $($tx:ident),* $(,)? ) => {
#[allow(non_snake_case)]
2024-08-08 17:18:30 +00:00
impl<Err, Req, Fut, Fun, $($tx,)*> RumaHandler<($($tx,)* Ruma<Req>,)> for Fun
where
2024-08-08 17:18:30 +00:00
Fun: Fn($($tx,)* Ruma<Req>,) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Result<Req::OutgoingResponse, Err>> + Send,
2026-04-13 16:20:47 -04:00
Req: IncomingRequest<Authentication: $crate::router::auth::CheckAuth> + Send + Sync + 'static,
2024-08-08 17:18:30 +00:00
Err: IntoResponse + Send,
<Req as IncomingRequest>::OutgoingResponse: Send,
$( $tx: FromRequestParts<State> + Send + Sync + 'static, )*
{
2024-08-08 17:18:30 +00:00
fn add_routes(&'static self, router: Router<State>) -> Router<State> {
use ruma::api::path_builder::PathBuilder;
Req::PATH_BUILDER
.all_paths()
.fold(router, |router, path| self.add_route(router, path))
}
2024-08-08 17:18:30 +00:00
fn add_route(&'static self, router: Router<State>, path: &str) -> Router<State> {
let action = |$($tx,)* req| self($($tx,)* req).map_ok(RumaResponse);
let method = method_to_filter(&Req::METHOD);
router.route(path, on(method, action))
}
}
}
}
ruma_handler!();
ruma_handler!(T1);
ruma_handler!(T1, T2);
ruma_handler!(T1, T2, T3);
ruma_handler!(T1, T2, T3, T4);
const fn method_to_filter(method: &Method) -> MethodFilter {
match *method {
| Method::DELETE => MethodFilter::DELETE,
| Method::GET => MethodFilter::GET,
| Method::HEAD => MethodFilter::HEAD,
| Method::OPTIONS => MethodFilter::OPTIONS,
| Method::PATCH => MethodFilter::PATCH,
| Method::POST => MethodFilter::POST,
| Method::PUT => MethodFilter::PUT,
| Method::TRACE => MethodFilter::TRACE,
| _ => panic!("Unsupported HTTP method"),
}
}