优化路由实现
This commit is contained in:
parent
f61181808e
commit
fe5dd45cfd
@ -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
|
||||||
|
@ -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()
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user