添加宏路由(临时提交)
This commit is contained in:
parent
a488c82067
commit
684095231d
@ -18,7 +18,7 @@ i18n = { path = "i18n" }
|
|||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
tokio = "1.36"
|
tokio = "1.36"
|
||||||
axum = "0.7"
|
axum = "0.7.7"
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tower-http = "0.5"
|
tower-http = "0.5"
|
||||||
validator = "0.17"
|
validator = "0.17"
|
||||||
|
@ -4,4 +4,8 @@
|
|||||||
- [*] 参考example中的jwt实现方式,移除context对extension的依赖?那么language-tag该怎么处理?
|
- [*] 参考example中的jwt实现方式,移除context对extension的依赖?那么language-tag该怎么处理?
|
||||||
- [ ] 参考rocket,移除参数的元组类型
|
- [ ] 参考rocket,移除参数的元组类型
|
||||||
- [ ] 模拟request_util能否避免涉及到的parts.clone()?
|
- [ ] 模拟request_util能否避免涉及到的parts.clone()?
|
||||||
- [ ] 能否自定义实现宏路由
|
- [ ] 能否自定义实现宏路由
|
||||||
|
|
||||||
|
|
||||||
|
### note
|
||||||
|
- 展开宏:cargo expand --manifest-path .\server\Cargo.toml controller::feedback_controller
|
@ -1,4 +1,4 @@
|
|||||||
use derive::Responsable;
|
use macros::Responsable;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::types::JsonValue;
|
use sqlx::types::JsonValue;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use derive::Responsable;
|
use macros::Responsable;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::entities::feedback::Feedback;
|
use crate::entities::feedback::Feedback;
|
||||||
|
0
feeback_controller_ex.rs
Normal file
0
feeback_controller_ex.rs
Normal file
0
feedback_controller_e.rs
Normal file
0
feedback_controller_e.rs
Normal file
@ -1,5 +1,3 @@
|
|||||||
use std::fmt::Display;
|
|
||||||
|
|
||||||
use axum::{async_trait, extract::{path::ErrorKind, rejection::PathRejection, FromRequestParts}};
|
use axum::{async_trait, extract::{path::ErrorKind, rejection::PathRejection, FromRequestParts}};
|
||||||
use http::request::Parts;
|
use http::request::Parts;
|
||||||
use i18n::{message, message_ids::MessageId};
|
use i18n::{message, message_ids::MessageId};
|
||||||
@ -13,7 +11,7 @@ pub struct PathVar<T>(pub T);
|
|||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<S, T> FromRequestParts<S> for PathVar<T>
|
impl<S, T> FromRequestParts<S> for PathVar<T>
|
||||||
where
|
where
|
||||||
T: DeserializeOwned + Send + Display,
|
T: DeserializeOwned + Send,
|
||||||
S: Send + Sync,
|
S: Send + Sync,
|
||||||
{
|
{
|
||||||
type Rejection = ResErr;
|
type Rejection = ResErr;
|
||||||
@ -25,7 +23,6 @@ where
|
|||||||
|
|
||||||
match axum::extract::Path::<T>::from_request_parts(parts, state).await {
|
match axum::extract::Path::<T>::from_request_parts(parts, state).await {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
tracing::info!("path params: {}", value.0);
|
|
||||||
Ok(Self(value.0))
|
Ok(Self(value.0))
|
||||||
},
|
},
|
||||||
Err(rejection) => {
|
Err(rejection) => {
|
||||||
|
@ -27,7 +27,9 @@ where
|
|||||||
type State = S;
|
type State = S;
|
||||||
|
|
||||||
fn typed_route(self, handler: TypedHandler<Self::State>) -> Self {
|
fn typed_route(self, handler: TypedHandler<Self::State>) -> Self {
|
||||||
|
tracing::info!("start add router");
|
||||||
let (path, method_router) = handler();
|
let (path, method_router) = handler();
|
||||||
|
tracing::info!("adding typed route: {} - {:?}", path, method_router);
|
||||||
self.route(path, method_router)
|
self.route(path, method_router)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "derive"
|
name = "macros"
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
|
140
macro/src/lib.rs
140
macro/src/lib.rs
@ -4,10 +4,11 @@ extern crate syn;
|
|||||||
|
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
|
||||||
use proc_macro::TokenStream; // 用于处理宏输入
|
use proc_macro::TokenStream; // 用于生成代码
|
||||||
use quote::quote; // 用于生成代码
|
use syn::{parse_macro_input, parse_quote, DeriveInput}; // 用于解析宏输入
|
||||||
use syn::{parse_macro_input, Data, DeriveInput, Fields}; // 用于解析宏输入
|
|
||||||
|
|
||||||
|
mod responsable;
|
||||||
|
mod route;
|
||||||
|
|
||||||
// 定义一个名为`responsable`的过程宏
|
// 定义一个名为`responsable`的过程宏
|
||||||
// #[proc_macro_derive(Responsable, attributes(status, headers))]
|
// #[proc_macro_derive(Responsable, attributes(status, headers))]
|
||||||
@ -15,128 +16,23 @@ use syn::{parse_macro_input, Data, DeriveInput, Fields}; // 用于解析宏输
|
|||||||
pub fn responsable(input: TokenStream) -> TokenStream {
|
pub fn responsable(input: TokenStream) -> TokenStream {
|
||||||
// 解析宏输入为`DeriveInput`
|
// 解析宏输入为`DeriveInput`
|
||||||
let input = parse_macro_input!(input as DeriveInput);
|
let input = parse_macro_input!(input as DeriveInput);
|
||||||
let name = &input.ident; // 获取结构体名称
|
|
||||||
|
|
||||||
// 根据数据类型生成不同的代码
|
// 根据数据类型生成不同的代码
|
||||||
let gen = match input.data {
|
responsable::gen_responsable(input)
|
||||||
Data::Struct(ref data) => match data.fields {
|
}
|
||||||
Fields::Named(ref _fields) => {
|
|
||||||
// // 处理命名字段
|
|
||||||
// let field_names = fields.named.iter().map(|f| &f.ident); // 获取所有字段名称
|
|
||||||
// let field_types = fields.named.iter().map(|f| &f.ty); // 获取所有字段类型
|
|
||||||
|
|
||||||
// // 获取`status`属性
|
// #[proc_macro_attribute]
|
||||||
// let status = match input.attrs.iter().find(|attr| attr.path().is_ident("status")) {
|
// pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
// Some(attr) => {
|
// route::gen_route(attr, item)
|
||||||
// let status_lit = attr.parse_args::<Ident>().unwrap(); // 解析`status`属性值
|
// // item
|
||||||
// quote! { #status_lit } // 生成状态码
|
// }
|
||||||
// },
|
|
||||||
// None => quote! { hyper::StatusCode::OK }, // 默认状态码为`OK`
|
|
||||||
// };
|
|
||||||
|
|
||||||
// // 获取`headers`属性
|
#[proc_macro_attribute]
|
||||||
// let headers = match input.attrs.iter().find(|attr| attr.path().is_ident("headers")) {
|
pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
// Some(attr) => {
|
route::gen_route(attr, item)
|
||||||
// let headers_lit = attr.parse_args::<Ident>().unwrap(); // 解析`headers`属性值
|
}
|
||||||
// quote! { #headers_lit } // 生成头部信息
|
|
||||||
// },
|
|
||||||
// None => quote! { hyper::HeaderMap::new() }, // 默认头部信息为空
|
|
||||||
// };
|
|
||||||
|
|
||||||
// 生成实现`IntoResponse` trait的代码
|
#[proc_macro_attribute]
|
||||||
quote! {
|
pub fn get(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
impl axum::response::IntoResponse for #name {
|
route::gen_get_route(attr, item)
|
||||||
fn into_response(self) -> axum::http::Response<axum::body::Body> {
|
|
||||||
let mut builder = hyper::Response::builder();
|
|
||||||
// .status(#status) // 设置状态码
|
|
||||||
// .headers(#headers); // 设置头部信息
|
|
||||||
|
|
||||||
let body = serde_json::to_string(&self).expect("Failed to serialize response"); // 序列化结构体为JSON字符串
|
|
||||||
|
|
||||||
axum::http::Response::new(axum::body::Body::from(body)) // 构建响应
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Fields::Unnamed(ref _fields) => {
|
|
||||||
// // 处理未命名字段
|
|
||||||
// let field_names = fields.unnamed.iter().enumerate().map(|(i, _)| i); // 获取所有字段索引
|
|
||||||
// let field_types = fields.unnamed.iter().map(|f| &f.ty); // 获取所有字段类型
|
|
||||||
|
|
||||||
// // 获取`status`属性
|
|
||||||
// let status = match input.attrs.iter().find(|attr| attr.path().is_ident("status")) {
|
|
||||||
// Some(attr) => {
|
|
||||||
// let status_lit = attr.parse_args::<Ident>().unwrap(); // 解析`status`属性值
|
|
||||||
// quote! { #status_lit } // 生成状态码
|
|
||||||
// },
|
|
||||||
// None => quote! { hyper::StatusCode::OK }, // 默认状态码为`OK`
|
|
||||||
// };
|
|
||||||
|
|
||||||
// // 获取`headers`属性
|
|
||||||
// let headers = match input.attrs.iter().find(|attr| attr.path().is_ident("headers")) {
|
|
||||||
// Some(attr) => {
|
|
||||||
// let headers_lit = attr.parse_args::<Ident>().unwrap(); // 解析`headers`属性值
|
|
||||||
// quote! { #headers_lit } // 生成头部信息
|
|
||||||
// },
|
|
||||||
// None => quote! { hyper::HeaderMap::new() }, // 默认头部信息为空
|
|
||||||
// };
|
|
||||||
|
|
||||||
// 生成实现`IntoResponse` trait的代码
|
|
||||||
quote! {
|
|
||||||
impl axum::response::IntoResponse for #name {
|
|
||||||
fn into_response(self) -> axum::http::Response<axum::body::Body> {
|
|
||||||
// let mut builder = hyper::Response::builder();
|
|
||||||
// .status(#status) // 设置状态码
|
|
||||||
// .headers(#headers); // 设置头部信息
|
|
||||||
|
|
||||||
let body = serde_json::to_string(&self).expect("Failed to serialize response"); // 序列化结构体为JSON字符串
|
|
||||||
|
|
||||||
axum::http::Response::new(axum::body::Body::from(body)) // 构建响应
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Fields::Unit => {
|
|
||||||
// // 处理无字段的结构体
|
|
||||||
// // 获取`status`属性
|
|
||||||
// let status = match input.attrs.iter().find(|attr| attr.path().is_ident("status")) {
|
|
||||||
// Some(attr) => {
|
|
||||||
// let status_lit = attr.parse_args::<Ident>().unwrap(); // 解析`status`属性值
|
|
||||||
// quote! { #status_lit } // 生成状态码
|
|
||||||
// },
|
|
||||||
// None => quote! { hyper::StatusCode::OK }, // 默认状态码为`OK`
|
|
||||||
// };
|
|
||||||
|
|
||||||
// // 获取`headers`属性
|
|
||||||
// let headers = match input.attrs.iter().find(|attr| attr.path().is_ident("headers")) {
|
|
||||||
// Some(attr) => {
|
|
||||||
// let headers_lit = attr.parse_args::<Ident>().unwrap(); // 解析`headers`属性值
|
|
||||||
// quote! { #headers_lit } // 生成头部信息
|
|
||||||
// },
|
|
||||||
// None => quote! { hyper::HeaderMap::new() }, // 默认头部信息为空
|
|
||||||
// };
|
|
||||||
|
|
||||||
// 生成实现`IntoResponse` trait的代码
|
|
||||||
quote! {
|
|
||||||
impl axum::response::IntoResponse for #name {
|
|
||||||
fn into_response(self) -> axum::http::Response<axum::body::Body> {
|
|
||||||
// let mut builder = hyper::Response::builder();
|
|
||||||
// .status(#status) // 设置状态码
|
|
||||||
// .headers(#headers); // 设置头部信息
|
|
||||||
|
|
||||||
let body = serde_json::to_string(&self).expect("Failed to serialize response"); // 序列化结构体为JSON字符串
|
|
||||||
|
|
||||||
axum::http::Response::new(hyper::body::Body::from(body)) // 构建响应
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Data::Enum(_) | Data::Union(_) => {
|
|
||||||
// 不支持枚举或联合体
|
|
||||||
unimplemented!("IntoResponse derive is not implemented for enums or unions.")
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
gen.into() // 将生成的代码转换为`TokenStream`
|
|
||||||
}
|
}
|
133
macro/src/responsable.rs
Normal file
133
macro/src/responsable.rs
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
extern crate proc_macro2;
|
||||||
|
extern crate quote;
|
||||||
|
extern crate syn;
|
||||||
|
|
||||||
|
extern crate proc_macro;
|
||||||
|
|
||||||
|
use proc_macro::TokenStream; // 用于处理宏输入
|
||||||
|
use quote::quote; // 用于生成代码
|
||||||
|
use syn::{Data, DeriveInput, Fields}; // 用于解析宏输入
|
||||||
|
|
||||||
|
pub fn gen_responsable(input: DeriveInput) -> TokenStream {
|
||||||
|
let name = &input.ident; // 获取结构体名称
|
||||||
|
let gen = match input.data {
|
||||||
|
Data::Struct(ref data) => match data.fields {
|
||||||
|
Fields::Named(ref _fields) => {
|
||||||
|
// // 处理命名字段
|
||||||
|
// let field_names = fields.named.iter().map(|f| &f.ident); // 获取所有字段名称
|
||||||
|
// let field_types = fields.named.iter().map(|f| &f.ty); // 获取所有字段类型
|
||||||
|
|
||||||
|
// // 获取`status`属性
|
||||||
|
// let status = match input.attrs.iter().find(|attr| attr.path().is_ident("status")) {
|
||||||
|
// Some(attr) => {
|
||||||
|
// let status_lit = attr.parse_args::<Ident>().unwrap(); // 解析`status`属性值
|
||||||
|
// quote! { #status_lit } // 生成状态码
|
||||||
|
// },
|
||||||
|
// None => quote! { hyper::StatusCode::OK }, // 默认状态码为`OK`
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // 获取`headers`属性
|
||||||
|
// let headers = match input.attrs.iter().find(|attr| attr.path().is_ident("headers")) {
|
||||||
|
// Some(attr) => {
|
||||||
|
// let headers_lit = attr.parse_args::<Ident>().unwrap(); // 解析`headers`属性值
|
||||||
|
// quote! { #headers_lit } // 生成头部信息
|
||||||
|
// },
|
||||||
|
// None => quote! { hyper::HeaderMap::new() }, // 默认头部信息为空
|
||||||
|
// };
|
||||||
|
|
||||||
|
// 生成实现`IntoResponse` trait的代码
|
||||||
|
quote! {
|
||||||
|
impl axum::response::IntoResponse for #name {
|
||||||
|
fn into_response(self) -> axum::http::Response<axum::body::Body> {
|
||||||
|
let mut builder = hyper::Response::builder();
|
||||||
|
// .status(#status) // 设置状态码
|
||||||
|
// .headers(#headers); // 设置头部信息
|
||||||
|
|
||||||
|
let body = serde_json::to_string(&self).expect("Failed to serialize response"); // 序列化结构体为JSON字符串
|
||||||
|
|
||||||
|
axum::http::Response::new(axum::body::Body::from(body)) // 构建响应
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Fields::Unnamed(ref _fields) => {
|
||||||
|
// // 处理未命名字段
|
||||||
|
// let field_names = fields.unnamed.iter().enumerate().map(|(i, _)| i); // 获取所有字段索引
|
||||||
|
// let field_types = fields.unnamed.iter().map(|f| &f.ty); // 获取所有字段类型
|
||||||
|
|
||||||
|
// // 获取`status`属性
|
||||||
|
// let status = match input.attrs.iter().find(|attr| attr.path().is_ident("status")) {
|
||||||
|
// Some(attr) => {
|
||||||
|
// let status_lit = attr.parse_args::<Ident>().unwrap(); // 解析`status`属性值
|
||||||
|
// quote! { #status_lit } // 生成状态码
|
||||||
|
// },
|
||||||
|
// None => quote! { hyper::StatusCode::OK }, // 默认状态码为`OK`
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // 获取`headers`属性
|
||||||
|
// let headers = match input.attrs.iter().find(|attr| attr.path().is_ident("headers")) {
|
||||||
|
// Some(attr) => {
|
||||||
|
// let headers_lit = attr.parse_args::<Ident>().unwrap(); // 解析`headers`属性值
|
||||||
|
// quote! { #headers_lit } // 生成头部信息
|
||||||
|
// },
|
||||||
|
// None => quote! { hyper::HeaderMap::new() }, // 默认头部信息为空
|
||||||
|
// };
|
||||||
|
|
||||||
|
// 生成实现`IntoResponse` trait的代码
|
||||||
|
quote! {
|
||||||
|
impl axum::response::IntoResponse for #name {
|
||||||
|
fn into_response(self) -> axum::http::Response<axum::body::Body> {
|
||||||
|
// let mut builder = hyper::Response::builder();
|
||||||
|
// .status(#status) // 设置状态码
|
||||||
|
// .headers(#headers); // 设置头部信息
|
||||||
|
|
||||||
|
let body = serde_json::to_string(&self).expect("Failed to serialize response"); // 序列化结构体为JSON字符串
|
||||||
|
|
||||||
|
axum::http::Response::new(axum::body::Body::from(body)) // 构建响应
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Fields::Unit => {
|
||||||
|
// // 处理无字段的结构体
|
||||||
|
// // 获取`status`属性
|
||||||
|
// let status = match input.attrs.iter().find(|attr| attr.path().is_ident("status")) {
|
||||||
|
// Some(attr) => {
|
||||||
|
// let status_lit = attr.parse_args::<Ident>().unwrap(); // 解析`status`属性值
|
||||||
|
// quote! { #status_lit } // 生成状态码
|
||||||
|
// },
|
||||||
|
// None => quote! { hyper::StatusCode::OK }, // 默认状态码为`OK`
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // 获取`headers`属性
|
||||||
|
// let headers = match input.attrs.iter().find(|attr| attr.path().is_ident("headers")) {
|
||||||
|
// Some(attr) => {
|
||||||
|
// let headers_lit = attr.parse_args::<Ident>().unwrap(); // 解析`headers`属性值
|
||||||
|
// quote! { #headers_lit } // 生成头部信息
|
||||||
|
// },
|
||||||
|
// None => quote! { hyper::HeaderMap::new() }, // 默认头部信息为空
|
||||||
|
// };
|
||||||
|
|
||||||
|
// 生成实现`IntoResponse` trait的代码
|
||||||
|
quote! {
|
||||||
|
impl axum::response::IntoResponse for #name {
|
||||||
|
fn into_response(self) -> axum::http::Response<axum::body::Body> {
|
||||||
|
// let mut builder = hyper::Response::builder();
|
||||||
|
// .status(#status) // 设置状态码
|
||||||
|
// .headers(#headers); // 设置头部信息
|
||||||
|
|
||||||
|
let body = serde_json::to_string(&self).expect("Failed to serialize response"); // 序列化结构体为JSON字符串
|
||||||
|
|
||||||
|
axum::http::Response::new(hyper::body::Body::from(body)) // 构建响应
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Data::Enum(_) | Data::Union(_) => {
|
||||||
|
// 不支持枚举或联合体
|
||||||
|
unimplemented!("IntoResponse derive is not implemented for enums or unions.")
|
||||||
|
},
|
||||||
|
};
|
||||||
|
gen.into()
|
||||||
|
}
|
168
macro/src/route.rs
Normal file
168
macro/src/route.rs
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
extern crate proc_macro2;
|
||||||
|
extern crate quote;
|
||||||
|
extern crate syn;
|
||||||
|
|
||||||
|
extern crate proc_macro;
|
||||||
|
|
||||||
|
use parse::{Parse, ParseStream};
|
||||||
|
use proc_macro::{Span, TokenStream}; use punctuated::Punctuated;
|
||||||
|
// 用于处理宏输入
|
||||||
|
use quote::quote; // 用于生成代码
|
||||||
|
use syn::*;
|
||||||
|
|
||||||
|
struct Args {
|
||||||
|
vars: Vec<syn::Expr>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for Args {
|
||||||
|
fn parse(input: ParseStream) -> syn::parse::Result<Self> {
|
||||||
|
let vars = Punctuated::<syn::Expr, syn::Token![,]>::parse_terminated(input)?;
|
||||||
|
|
||||||
|
Ok(Args {
|
||||||
|
vars: vars.into_iter().collect(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Args {
|
||||||
|
pub fn get_method(&self) -> syn::Result<syn::Expr> {
|
||||||
|
match self.vars.get(0) {
|
||||||
|
Some(var) => Ok(var.clone()),
|
||||||
|
None => return Err(syn::Error::new(
|
||||||
|
Span::call_site().into(),
|
||||||
|
"No Method was provided"
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_route(&self) -> syn::Result<syn::Expr> {
|
||||||
|
match self.vars.get(0) {
|
||||||
|
Some(var) => Ok(var.clone()),
|
||||||
|
None => return Err(syn::Error::new(
|
||||||
|
Span::call_site().into(),
|
||||||
|
"No Route was provided"
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gen_route(attr: TokenStream, item: TokenStream) -> 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 method = args.get_method().unwrap();
|
||||||
|
let route = args.get_route().unwrap();
|
||||||
|
|
||||||
|
let expanded = quote! {
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#vis struct #ident;
|
||||||
|
|
||||||
|
impl #ident {
|
||||||
|
#vis fn route() -> axum::Router {
|
||||||
|
#func
|
||||||
|
|
||||||
|
axum::Router::new().route(#route, #method (#ident))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
expanded.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gen_get_route(attr: TokenStream, item: TokenStream) -> 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_route().unwrap();
|
||||||
|
|
||||||
|
let expanded = quote! {
|
||||||
|
#vis fn #ident () -> (&'static str, axum::routing::method_routing::MethodRouter) {
|
||||||
|
#func
|
||||||
|
|
||||||
|
(#route, axum::routing::get(#ident))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
expanded.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gen_post_route(attr: TokenStream, item: TokenStream) -> 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_route().unwrap();
|
||||||
|
|
||||||
|
let expanded = quote! {
|
||||||
|
#vis fn #ident () -> (&'static str, axum::routing::method_routing::MethodRouter) {
|
||||||
|
#func
|
||||||
|
|
||||||
|
(#route, axum::routing::post(#ident))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
expanded.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gen_delete_route(attr: TokenStream, item: TokenStream) -> 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_route().unwrap();
|
||||||
|
|
||||||
|
let expanded = quote! {
|
||||||
|
#vis fn #ident () -> (&'static str, axum::routing::method_routing::MethodRouter) {
|
||||||
|
#func
|
||||||
|
|
||||||
|
(#route, axum::routing::delete(#ident))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
expanded.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gen_put_route(attr: TokenStream, item: TokenStream) -> 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_route().unwrap();
|
||||||
|
|
||||||
|
let expanded = quote! {
|
||||||
|
#vis fn #ident () -> (&'static str, axum::routing::method_routing::MethodRouter) {
|
||||||
|
#func
|
||||||
|
|
||||||
|
(#route, axum::routing::put(#ident))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
expanded.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gen_option_route(attr: TokenStream, item: TokenStream) -> 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_route().unwrap();
|
||||||
|
|
||||||
|
let expanded = quote! {
|
||||||
|
#vis fn #ident () -> (&'static str, axum::routing::method_routing::MethodRouter) {
|
||||||
|
#func
|
||||||
|
|
||||||
|
(#route, axum::routing::option(#ident))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
expanded.into()
|
||||||
|
}
|
@ -1,10 +1,14 @@
|
|||||||
|
extern crate macros;
|
||||||
|
|
||||||
use domain::dto::feedback::FeedbackAdd;
|
use domain::dto::feedback::FeedbackAdd;
|
||||||
use domain::dto::pageable::PageParams;
|
use domain::dto::pageable::PageParams;
|
||||||
use domain::vo::feedback::FeedbackPageable;
|
use domain::vo::feedback::FeedbackPageable;
|
||||||
use library::context::Context;
|
use library::context::Context;
|
||||||
|
use library::extractor::path_extractor::PathVar;
|
||||||
use library::model::response::ResResult;
|
use library::model::response::ResResult;
|
||||||
use library::extractor::body_extractor::JsonBody;
|
use library::extractor::body_extractor::JsonBody;
|
||||||
use library::extractor::query_extractor::QueryParams;
|
use library::extractor::query_extractor::QueryParams;
|
||||||
|
use macros::get;
|
||||||
|
|
||||||
use crate::service;
|
use crate::service;
|
||||||
|
|
||||||
@ -31,4 +35,18 @@ pub async fn get_feedback_list_by_page(
|
|||||||
page_params.page_size.unwrap(),
|
page_params.page_size.unwrap(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[route(get, "/feedback/:page/:pageSize")]
|
||||||
|
#[get("/feedback/:page/:pageSize")]
|
||||||
|
pub async fn get_feedback_list(
|
||||||
|
context: Context,
|
||||||
|
PathVar(page_params): PathVar<PageParams>,
|
||||||
|
) -> ResResult<FeedbackPageable> {
|
||||||
|
service::feedback_service::get_feedback_list_by_page(
|
||||||
|
context,
|
||||||
|
page_params.page.unwrap(),
|
||||||
|
page_params.page_size.unwrap(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
@ -1,10 +1,16 @@
|
|||||||
use axum::{routing::post, Router};
|
use axum::{routing::{get, post, MethodRouter}, Router};
|
||||||
|
use library::typed_router::TypedRouter;
|
||||||
|
|
||||||
pub mod account_controller;
|
pub mod account_controller;
|
||||||
pub mod feedback_controller;
|
pub mod feedback_controller;
|
||||||
|
|
||||||
pub fn init() -> Router {
|
pub fn init() -> Router {
|
||||||
Router::new()
|
// let a = feedback_controller::get_feedback_list;
|
||||||
|
|
||||||
|
// axum::routing::method_routing::MethodRouter::new()
|
||||||
|
|
||||||
|
|
||||||
|
let router = Router::new()
|
||||||
.route(
|
.route(
|
||||||
"/account/google",
|
"/account/google",
|
||||||
post(account_controller::authenticate_google),
|
post(account_controller::authenticate_google),
|
||||||
@ -22,4 +28,17 @@ pub fn init() -> Router {
|
|||||||
post(feedback_controller::add_feedback)
|
post(feedback_controller::add_feedback)
|
||||||
.get(feedback_controller::get_feedback_list_by_page)
|
.get(feedback_controller::get_feedback_list_by_page)
|
||||||
)
|
)
|
||||||
}
|
.typed_route(feedback_controller::get_feedback_list)
|
||||||
|
// .merge(feedback_controller::get_feedback_list::route())
|
||||||
|
// .typed_route(route)
|
||||||
|
// .route(
|
||||||
|
// "/feedback/:page/:pageSize",
|
||||||
|
// get(feedback_controller::get_feedback_list)
|
||||||
|
// )
|
||||||
|
;
|
||||||
|
return router;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn route() -> (&'static str, MethodRouter) {
|
||||||
|
// ("/feedback", axum::routing::get(feedback_controller::get_feedback_list_by_page))
|
||||||
|
// }
|
Loading…
Reference in New Issue
Block a user