framework_web_axum/
router.rs1use crate::AxumContext;
2use crate::context::scope_axum;
3use framework_web::{
4 WebContext, WebError, WebMethod, WebResponse, WebRoute, scope_web, use_web, web_api_iter,
5};
6use futures_util::future::BoxFuture;
7use std::collections::HashMap as Map;
8use std::collections::hash_map::Entry;
9use std::sync::Arc;
10
11pub type WebRouteResultFuture = BoxFuture<'static, anyhow::Result<WebResponse>>;
13
14pub type WebRouteWrapper = Arc<dyn Fn(Arc<WebRoute>) -> WebRouteResultFuture + Send + Sync>;
16
17fn default_wrapper() -> WebRouteWrapper {
19 Arc::new(|route| Box::pin(async move { Ok(route.invoke().await) }))
20}
21
22pub struct WebRouter {
24 routes: Map<WebMethod, Map<String, Arc<WebRoute>>>,
25 wrapper: WebRouteWrapper,
26}
27
28impl WebRouter {
29 pub fn new(wrapper: Option<WebRouteWrapper>) -> Self {
30 let mut routes: Map<WebMethod, Map<String, Arc<WebRoute>>> = Map::new();
31 for route in web_api_iter() {
32 let route = Arc::new(route);
33 match routes.entry(route.method.clone()) {
34 Entry::Occupied(mut methods) => {
35 methods.get_mut().insert(route.path.clone(), route);
36 }
37 Entry::Vacant(methods) => {
38 methods.insert(Map::from([(route.path.clone(), route)]));
39 }
40 }
41 }
42 Self {
43 routes,
44 wrapper: wrapper.unwrap_or_else(default_wrapper),
45 }
46 }
47
48 pub async fn invoke(
50 &self,
51 web_context: WebContext,
52 axum_context: AxumContext,
53 ) -> anyhow::Result<WebResponse> {
54 let web_context = Arc::new(web_context);
55 let axum_context = Arc::new(axum_context);
56 scope_axum(
57 axum_context,
58 scope_web(web_context, async {
59 let route = self.find().await?;
60 (self.wrapper)(route).await
61 }),
62 )
63 .await
64 }
65
66 async fn find(&self) -> anyhow::Result<Arc<WebRoute>> {
68 let context = use_web()?;
69 let request = context.request();
70 let path = request.path.trim_matches('/');
71 self.routes
72 .get(&request.method)
73 .and_then(|routes| routes.get(path))
74 .cloned()
75 .ok_or_else(|| WebError::not_found("请求接口不存在").into())
76 }
77}