mirror of
https://github.com/DefectingCat/phthonus
synced 2025-07-15 16:41:32 +00:00
feat(axum-xitca): add json validation
This commit is contained in:
179
frameworks/Rust/axum-xitca/Cargo.lock
generated
179
frameworks/Rust/axum-xitca/Cargo.lock
generated
@ -71,7 +71,7 @@ checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -228,6 +228,41 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
@ -376,6 +411,22 @@ version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
|
||||
dependencies = [
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-uring"
|
||||
version = "0.6.4"
|
||||
@ -643,6 +694,7 @@ dependencies = [
|
||||
"tower-http",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"validator",
|
||||
"xitca-http",
|
||||
"xitca-io",
|
||||
"xitca-server",
|
||||
@ -675,6 +727,30 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.86"
|
||||
@ -802,7 +878,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -835,7 +911,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -927,6 +1003,22 @@ version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.77"
|
||||
@ -967,7 +1059,7 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1011,6 +1103,21 @@ dependencies = [
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec_macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.40.0"
|
||||
@ -1037,7 +1144,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1144,7 +1251,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1195,18 +1302,44 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.10.0"
|
||||
@ -1216,6 +1349,36 @@ dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "validator"
|
||||
version = "0.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db79c75af171630a3148bd3e6d7c4f42b6a9a014c2945bc5ed0020cbb8d9478e"
|
||||
dependencies = [
|
||||
"idna",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"url",
|
||||
"validator_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "validator_derive"
|
||||
version = "0.18.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df0bcf92720c40105ac4b2dda2a4ea3aa717d4d6a862cc217da653a4bd5c6b10"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"once_cell",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
version = "0.1.0"
|
||||
@ -1256,7 +1419,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.77",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@ -1278,7 +1441,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.77",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
@ -8,6 +8,7 @@ tokio = { version = "1.40.0", features = ["full"] }
|
||||
axum = { version = "0.7.6", default-features = false, features = [
|
||||
"json",
|
||||
"query",
|
||||
"form",
|
||||
] }
|
||||
xitca-server = { version = "0.4.0", features = ["io-uring"] }
|
||||
xitca-http = { version = "0.6.0", features = ["io-uring"] }
|
||||
@ -29,3 +30,4 @@ serde_repr = "0.1.19"
|
||||
http-body = "1.0.1"
|
||||
xitca-unsafe-collection = "0.2.0"
|
||||
jsonwebtoken = "9.3.0"
|
||||
validator = { version = "0.18.1", features = ["derive"] }
|
||||
|
@ -20,6 +20,8 @@ pub enum AppError {
|
||||
AxumFormRejection(#[from] FormRejection),
|
||||
#[error(transparent)]
|
||||
AxumJsonRejection(#[from] JsonRejection),
|
||||
#[error(transparent)]
|
||||
ValidationError(#[from] validator::ValidationErrors),
|
||||
// route
|
||||
// 路由通常错误 错误信息直接返回用户
|
||||
// #[error("{0}")]
|
||||
@ -74,17 +76,21 @@ impl IntoResponse for AppError {
|
||||
use ErrorCode::*;
|
||||
|
||||
let (status_code, code, err_message) = match self {
|
||||
// route
|
||||
// AppError::AuthorizeFailed(err) => {
|
||||
// (StatusCode::UNAUTHORIZED, AuthorizeFailed, err.to_string())
|
||||
// }
|
||||
// AppError::UserConflict(err) => (StatusCode::CONFLICT, UserConflict, err.to_string()),
|
||||
AppError::Any(err) => log_internal_error(err),
|
||||
AppError::AxumFormRejection(_) | AppError::AxumJsonRejection(_) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
ParameterIncorrect,
|
||||
self.to_string(),
|
||||
),
|
||||
// route
|
||||
// AppError::AuthorizeFailed(err) => {
|
||||
// (StatusCode::UNAUTHORIZED, AuthorizeFailed, err.to_string())
|
||||
// }
|
||||
// AppError::UserConflict(err) => (StatusCode::CONFLICT, UserConflict, err.to_string()),
|
||||
AppError::ValidationError(_) => {
|
||||
let message = format!("Input validation error: [{self}]").replace('\n', ", ");
|
||||
(StatusCode::BAD_REQUEST, ParameterIncorrect, message)
|
||||
}
|
||||
};
|
||||
let body = Json(json!({
|
||||
"code": code,
|
||||
|
@ -6,7 +6,7 @@ use axum::{
|
||||
http::{request::Parts, StatusCode, Uri},
|
||||
middleware,
|
||||
response::{IntoResponse, Response},
|
||||
routing::get,
|
||||
routing::{get, post},
|
||||
Json, RequestPartsExt, Router,
|
||||
};
|
||||
use serde::Serialize;
|
||||
@ -20,6 +20,7 @@ use crate::{
|
||||
};
|
||||
|
||||
mod json;
|
||||
mod user;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct RouteResponse<T>
|
||||
@ -49,6 +50,7 @@ pub fn routes() -> Router {
|
||||
let router = Router::new()
|
||||
.route("/", get(hello).post(hello))
|
||||
.route("/json", get(json::json).post(json::json))
|
||||
.route("/user", post(user::register))
|
||||
.layer(
|
||||
ServiceBuilder::new()
|
||||
.layer(middleware::from_fn(add_version))
|
||||
|
32
frameworks/Rust/axum-xitca/src/routes/user.rs
Normal file
32
frameworks/Rust/axum-xitca/src/routes/user.rs
Normal file
@ -0,0 +1,32 @@
|
||||
use crate::utils::validator::ValidatedJson;
|
||||
|
||||
use super::{RouteResponse, RouteResult};
|
||||
use axum::Json;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator::Validate;
|
||||
|
||||
#[derive(Serialize, Deserialize, Validate)]
|
||||
pub struct RegisterPayload {
|
||||
#[validate(length(min = 1, message = "cannot be empyt"))]
|
||||
pub username: String,
|
||||
pub email: String,
|
||||
#[validate(length(min = 1, message = "cannot be empyt"))]
|
||||
pub password: String,
|
||||
}
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
pub struct RegisterData {
|
||||
pub username: String,
|
||||
}
|
||||
|
||||
pub async fn register(
|
||||
ValidatedJson(user): ValidatedJson<RegisterPayload>,
|
||||
) -> RouteResult<RegisterData> {
|
||||
let data = RegisterData {
|
||||
username: user.username,
|
||||
};
|
||||
let res = RouteResponse {
|
||||
data,
|
||||
..Default::default()
|
||||
};
|
||||
Ok(Json(res))
|
||||
}
|
@ -2,6 +2,7 @@ use tokio::signal;
|
||||
use tracing_subscriber::{fmt, prelude::*, registry, EnvFilter};
|
||||
|
||||
pub mod jwt;
|
||||
pub mod validator;
|
||||
|
||||
/// Initializes the logger for tracing.
|
||||
pub fn init_logger() {
|
||||
|
28
frameworks/Rust/axum-xitca/src/utils/validator.rs
Normal file
28
frameworks/Rust/axum-xitca/src/utils/validator.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use axum::{
|
||||
async_trait,
|
||||
extract::{rejection::FormRejection, FromRequest, Request},
|
||||
Form, Json,
|
||||
};
|
||||
use serde::de::DeserializeOwned;
|
||||
use validator::Validate;
|
||||
|
||||
use crate::error::{AppError, AppResult};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct ValidatedJson<T>(pub T);
|
||||
|
||||
#[async_trait]
|
||||
impl<T, S> FromRequest<S> for ValidatedJson<T>
|
||||
where
|
||||
T: DeserializeOwned + Validate,
|
||||
S: Send + Sync,
|
||||
Form<T>: FromRequest<S, Rejection = FormRejection>,
|
||||
{
|
||||
type Rejection = AppError;
|
||||
|
||||
async fn from_request(req: Request, state: &S) -> AppResult<Self, Self::Rejection> {
|
||||
let Json(value) = Json::<T>::from_request(req, state).await?;
|
||||
value.validate()?;
|
||||
Ok(ValidatedJson(value))
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user