优化路由实现

This commit is contained in:
李运家 2025-02-08 16:13:54 +08:00
parent f61181808e
commit fe5dd45cfd
2 changed files with 21 additions and 104 deletions

View File

@ -20,7 +20,6 @@ macro_rules! submit_router_method {
pub fn get_router() -> Router { pub fn get_router() -> Router {
let mut router = Router::new(); let mut router = Router::new();
for method in inventory::iter::<&dyn RouteMethod> { for method in inventory::iter::<&dyn RouteMethod> {
// result.push(Arc::new(method.ge_task()));
router = method.ge_router(router); router = method.ge_router(router);
} }
router router

View File

@ -22,32 +22,7 @@ struct RouteArgs {
// 实现 Parse trait 以支持解析参数 // 实现 Parse trait 以支持解析参数
impl Parse for RouteArgs { impl Parse for RouteArgs {
fn parse(input: ParseStream) -> Result<Self> { fn parse(input: ParseStream) -> Result<Self> {
// 使用Meta解析 begin
// let args = Punctuated::<syn::Meta, syn::Token![,]>::parse_terminated(input)?;
// let mut path = None;
// let mut methods = Vec::new();
// for arg in args {
// if let Meta::NameValue(nv) = arg {
// if nv.path.is_ident("method") {
// if let Expr::Array(ExprArray { elems, .. }) = nv.value {
// for elem in elems {
// if let Expr::Lit(syn::ExprLit { lit: Lit::Str(lit_str), .. }) = elem {
// methods.push(lit_str.value());
// }
// }
// }
// } else if nv.path.is_ident("path") {
// if let Expr::Lit(ExprLit { lit: Lit::Str(lit_str), .. }) = nv.value {
// path = Some(lit_str.value());
// }
// }
// }
// }
// let path = path.expect("Expected a path argument");
// 使用Meta解析 end
let args = Punctuated::<Expr, Token![,]>::parse_terminated(input)?; let args = Punctuated::<Expr, Token![,]>::parse_terminated(input)?;
let mut path = None; let mut path = None;
let mut methods = Vec::new(); let mut methods = Vec::new();
@ -57,7 +32,10 @@ impl Parse for RouteArgs {
lit: Lit::Str(lit_str), lit: Lit::Str(lit_str),
.. ..
}) => { }) => {
path = Some(lit_str.value()); let path_str = lit_str.value();
// 验证路由路径
validate_route_path(&path_str)?;
path = Some(path_str);
} }
Expr::Assign(assign) => { Expr::Assign(assign) => {
if let Expr::Path(path) = *assign.left { if let Expr::Path(path) = *assign.left {
@ -80,43 +58,24 @@ impl Parse for RouteArgs {
} }
} }
let path = path.expect("路由参数不能为空"); let path = path.ok_or_else(|| Error::new(
Span::call_site().into(),
"路由路径参数不能为空",
))?;
Ok(RouteArgs { path, methods }) Ok(RouteArgs { path, methods })
} }
} }
struct Args { // 添加路由参数验证
vars: Vec<Expr>, fn validate_route_path(path: &str) -> Result<()> {
} if !path.starts_with('/') {
return Err(Error::new(
impl Parse for Args { Span::call_site().into(),
fn parse(input: ParseStream) -> Result<Self> { "路由路径必须以'/'开头",
let vars = Punctuated::<Expr, Token![,]>::parse_terminated(input)?; ));
Ok(Args {
vars: vars.into_iter().collect(),
})
}
}
impl Args {
pub fn get_arg(&self, index: usize) -> Result<Option<Expr>> {
match self.vars.get(index) {
Some(var) => Ok(Some(var.to_owned())),
None => {
// 第一个参数使路由url必须存在其他的参数根据实际需求进一步解析
if index != 0 {
Ok(None)
} else {
Err(Error::new(
Span::call_site().into(),
"route must have one argument",
))
}
}
}
} }
Ok(())
} }
pub fn gen_route(attr: TokenStream, item: TokenStream, method: &str) -> TokenStream { pub fn gen_route(attr: TokenStream, item: TokenStream, method: &str) -> TokenStream {
@ -150,11 +109,12 @@ pub fn gen_route(attr: TokenStream, item: TokenStream, method: &str) -> TokenStr
#func #func
} }
impl library::typed_router::RouteMethod for #ident { impl library::typed_router::RouteMethod for #ident {
fn ge_router(&self, router: axum::Router) -> axum::Router { fn ge_router(&self, mut router: axum::Router) -> axum::Router {
let methods = vec![#(#method_routers),*]; let methods = vec![#(#method_routers),*];
methods.into_iter().fold(router, |router, (path, method_router)| { for (path, method_router) in methods {
router.route(path, method_router) router = router.route(path, method_router);
}) }
router
} }
} }
::library::submit_router_method!(#ident); ::library::submit_router_method!(#ident);
@ -162,45 +122,3 @@ pub fn gen_route(attr: TokenStream, item: TokenStream, method: &str) -> TokenStr
TokenStream::from(generated) TokenStream::from(generated)
} }
#[allow(dead_code)]
pub fn gen_dyn_route(attr: TokenStream, item: TokenStream, method: &str) -> TokenStream {
let args = parse_macro_input!(attr as Args);
let func = parse_macro_input!(item as ItemFn);
let vis = func.vis.clone();
let ident = func.sig.ident.clone();
let route = args.get_arg(0).unwrap().unwrap();
let method_option = args.get_arg(1);
match method_option {
Ok(method) => {
if let Some(Expr::Assign(methods_value)) = method {
println!("method is {:?}", methods_value);
// if let Expr::Path(left) = methods_value.left {
// left.path.segments[0].ident.eq("d") {
// }
// }
// if let Expr::Lit(right) = methods_value.right {
// }
}
}
Err(err) => {
println!("error is {}", err);
}
}
let method_name: Ident = Ident::new(method, route.span());
let expanded = quote! {
#vis fn #ident () -> (&'static str, axum::routing::method_routing::MethodRouter) {
#func
(#route, axum::routing::#method_name(#ident))
}
};
expanded.into()
}