diff --git a/Cargo.toml b/Cargo.toml index 412dabe..4357a8d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "axum-valid" -version = "0.21.0" +version = "0.22.0" description = "Provides validation extractors for your Axum application, allowing you to validate data using validator, garde, validify or all of them." authors = ["GengTeng "] license = "MIT" @@ -26,8 +26,8 @@ features = ["full", "aide"] [dependencies] axum = { version = "0.8", default-features = false } -garde = { version = "0.21.0", optional = true } -validator = { version = "0.19.0", optional = true } +garde = { version = "0.22.0", optional = true } +validator = { version = "0.20.0", optional = true } validify = { version = "1.4.0", optional = true } [dependencies.axum-extra] @@ -36,38 +36,38 @@ default-features = false optional = true [dependencies.axum-serde] -version = "0.7.0" +version = "0.8.1" optional = true [dependencies.axum_typed_multipart] -version = "0.14" +version = "0.15.1" optional = true [dependencies.serde] -version = "1.0.210" +version = "1.0.217" optional = true [dependencies.aide] -version = "0.13.4" +version = "0.14.0" optional = true [dev-dependencies] anyhow = "1.0.87" axum = { version = "0.8", features = ["macros"] } -tokio = { version = "1.34.0", features = ["full"] } +tokio = { version = "1.43.0", features = ["full"] } reqwest = { version = "0.12.3", features = ["json", "multipart"] } serde = { version = "1.0.195", features = ["derive"] } -validator = { version = "0.19.0", features = ["derive"] } -garde = { version = "0.21.0", features = ["serde", "derive"] } +validator = { version = "0.20.0", features = ["derive"] } +garde = { version = "0.22.0", features = ["serde", "derive"] } serde_json = "1.0.108" -serde_yaml = "0.9.27" -quick-xml = { version = "0.36.1", features = ["serialize"] } +serde_yaml = "0.9.33" +quick-xml = { version = "0.37.1", features = ["serialize"] } ciborium = { version = "0.2.2" } -toml = "0.8.8" +toml = "0.8.14" mime = "0.3.17" -prost = "0.12.3" -once_cell = "1.18.0" -rmp-serde = "1.1.2" +prost = "0.13.4" +once_cell = "1.20.2" +rmp-serde = "1.3.0" [features] default = ["basic", "validator"] diff --git a/src/extra.rs b/src/extra.rs index 455c5f7..e16fc9f 100644 --- a/src/extra.rs +++ b/src/extra.rs @@ -61,7 +61,6 @@ //! } //! } //! -//! #[axum::async_trait] //! impl FromRequestParts for Parameter //! where //! S: Send + Sync, @@ -108,7 +107,7 @@ //! } //! } //! -//! #[axum::async_trait] +//! //! impl FromRequestParts for Parameter //! where //! S: Send + Sync, @@ -189,7 +188,7 @@ //! } //! } //! -//! #[axum::async_trait] +//! //! impl FromRequestParts for Parameter //! where //! S: Send + Sync, @@ -242,7 +241,7 @@ //! } //! } //! -//! #[axum::async_trait] +//! //! impl FromRequestParts for Parameter //! where //! S: Send + Sync, @@ -332,7 +331,7 @@ //! } //! } //! -//! #[axum::async_trait] +//! //! impl FromRequestParts for Parameter //! where //! S: Send + Sync, @@ -407,7 +406,7 @@ //! } //! } //! -//! #[axum::async_trait] +//! //! impl FromRequestParts for Parameter //! where //! S: Send + Sync, diff --git a/src/extra/form.rs b/src/extra/form.rs index e7107e7..f0d803e 100644 --- a/src/extra/form.rs +++ b/src/extra/form.rs @@ -143,7 +143,7 @@ mod tests { use serde::Serialize; impl ValidTest for Form { - const ERROR_STATUS_CODE: StatusCode = StatusCode::BAD_REQUEST; + const ERROR_STATUS_CODE: StatusCode = StatusCode::UNPROCESSABLE_ENTITY; fn set_valid_request(builder: RequestBuilder) -> RequestBuilder { builder.form(T::valid()) diff --git a/src/extra/typed_path.rs b/src/extra/typed_path.rs index 6ebe3f2..291c659 100644 --- a/src/extra/typed_path.rs +++ b/src/extra/typed_path.rs @@ -29,7 +29,7 @@ //! } //! //! #[derive(TypedPath, Deserialize, Validate)] -//! #[typed_path("/extra_typed_path/:v0/:v1")] +//! #[typed_path("/extra_typed_path/{v0}/{v1}")] //! struct Parameter { //! #[validate(range(min = 5, max = 10))] //! v0: i32, @@ -63,7 +63,7 @@ //! } //! //! #[derive(TypedPath, Deserialize, Validate)] -//! #[typed_path("/extra_typed_path/:v0/:v1")] +//! #[typed_path("/extra_typed_path/{v0}/{v1}")] //! struct Parameter { //! #[garde(range(min = 5, max = 10))] //! v0: i32, diff --git a/src/garde.rs b/src/garde.rs index 58cd504..c32d821 100644 --- a/src/garde.rs +++ b/src/garde.rs @@ -61,7 +61,10 @@ impl aide::OperationInput for Garde where T: aide::OperationInput, { - fn operation_input(ctx: &mut aide::gen::GenContext, operation: &mut aide::openapi::Operation) { + fn operation_input( + ctx: &mut aide::generate::GenContext, + operation: &mut aide::openapi::Operation, + ) { T::operation_input(ctx, operation); } } diff --git a/src/garde/test.rs b/src/garde/test.rs index 48ce0b2..a161f57 100644 --- a/src/garde/test.rs +++ b/src/garde/test.rs @@ -1,3 +1,6 @@ +//! # Test for garde +//! + #![cfg(feature = "garde")] use crate::tests::{ValidTest, ValidTestParameter}; @@ -15,6 +18,8 @@ use std::net::SocketAddr; use std::ops::Deref; use tokio::net::TcpListener; +/// ParametersGarde +/// #[derive(Clone, Deserialize, Serialize, Validate, Eq, PartialEq)] #[cfg_attr(feature = "extra_protobuf", derive(prost::Message))] #[cfg_attr( @@ -434,6 +439,8 @@ async fn test_main() -> anyhow::Result<()> { Ok(()) } +/// Test Executor +/// #[derive(Debug, Clone)] pub struct TestExecutor { client: reqwest::Client, @@ -496,6 +503,7 @@ impl TestExecutor { Ok(()) } + /// Get reqwest client reference pub fn client(&self) -> &reqwest::Client { &self.client } @@ -514,7 +522,7 @@ pub async fn check_json(type_name: &'static str, response: reqwest::Response) { } mod route { - pub const PATH: &str = "/path/:v0/:v1"; + pub const PATH: &str = "/path/{v0}/{v1}"; pub const QUERY: &str = "/query"; pub const FORM: &str = "/form"; pub const JSON: &str = "/json"; @@ -692,7 +700,7 @@ mod extra { } // 1.3. Implement your extractor (`FromRequestParts` or `FromRequest`) - #[axum::async_trait] + impl FromRequestParts for ParametersGarde where S: Send + Sync, @@ -812,11 +820,11 @@ mod extra_typed_path { use serde::Deserialize; pub mod route { - pub const EXTRA_TYPED_PATH: &str = "/extra_typed_path/:v0/:v1"; + pub const EXTRA_TYPED_PATH: &str = "/extra_typed_path/{v0}/{v1}"; } #[derive(Validate, TypedPath, Deserialize)] - #[typed_path("/extra_typed_path/:v0/:v1")] + #[typed_path("/extra_typed_path/{v0}/{v1}")] pub struct TypedPathParam { #[garde(range(min = 5, max = 10))] v0: i32, diff --git a/src/validator.rs b/src/validator.rs index 0531250..4b07b2a 100644 --- a/src/validator.rs +++ b/src/validator.rs @@ -61,7 +61,10 @@ impl aide::OperationInput for Valid where T: aide::OperationInput, { - fn operation_input(ctx: &mut aide::gen::GenContext, operation: &mut aide::openapi::Operation) { + fn operation_input( + ctx: &mut aide::generate::GenContext, + operation: &mut aide::openapi::Operation, + ) { T::operation_input(ctx, operation); } } @@ -117,7 +120,10 @@ impl aide::OperationInput for ValidEx where T: aide::OperationInput, { - fn operation_input(ctx: &mut aide::gen::GenContext, operation: &mut aide::openapi::Operation) { + fn operation_input( + ctx: &mut aide::generate::GenContext, + operation: &mut aide::openapi::Operation, + ) { T::operation_input(ctx, operation); } } @@ -216,6 +222,7 @@ where } } +/// basic tests for validator #[cfg(test)] pub mod tests { use super::*; diff --git a/src/validator/test.rs b/src/validator/test.rs index aa2e10d..6e60bed 100644 --- a/src/validator/test.rs +++ b/src/validator/test.rs @@ -1,3 +1,6 @@ +//! # Test for validator +//! + #![cfg(feature = "validator")] use crate::tests::{ValidTest, ValidTestParameter}; @@ -16,6 +19,8 @@ use std::sync::Arc; use tokio::net::TcpListener; use validator::{Validate, ValidateArgs, ValidationError}; +/// Parameters +/// #[derive(Clone, Deserialize, Serialize, Validate, Eq, PartialEq)] #[cfg_attr(feature = "extra_protobuf", derive(prost::Message))] #[cfg_attr( @@ -31,6 +36,8 @@ pub struct Parameters { v1: String, } +/// ParametersEx +/// #[derive(Clone, Deserialize, Serialize, Validate, Eq, PartialEq)] #[cfg_attr(feature = "extra_protobuf", derive(prost::Message))] #[cfg_attr( @@ -69,6 +76,8 @@ struct ParametersExValidationArgumentsInner { v1_length_range: RangeInclusive, } +/// ParametersExValidationArguments +/// #[derive(Debug, Clone, Default)] pub struct ParametersExValidationArguments { inner: Arc, @@ -663,6 +672,7 @@ async fn test_main() -> anyhow::Result<()> { Ok(()) } +/// Test Executor #[derive(Debug, Clone)] pub struct TestExecutor { client: reqwest::Client, @@ -725,6 +735,7 @@ impl TestExecutor { Ok(()) } + /// Get reqwest client reference pub fn client(&self) -> &reqwest::Client { &self.client } @@ -743,8 +754,8 @@ pub async fn check_json(type_name: &'static str, response: reqwest::Response) { } mod route { - pub const PATH: &str = "/path/:v0/:v1"; - pub const PATH_EX: &str = "/path_ex/:v0/:v1"; + pub const PATH: &str = "/path/{v0}/{v1}"; + pub const PATH_EX: &str = "/path_ex/{v0}/{v1}"; pub const QUERY: &str = "/query"; pub const QUERY_EX: &str = "/query_ex"; pub const FORM: &str = "/form"; @@ -1036,7 +1047,7 @@ mod extra { } // 1.3. Implement your extractor (`FromRequestParts` or `FromRequest`) - #[axum::async_trait] + impl FromRequestParts for Parameters where S: Send + Sync, @@ -1052,7 +1063,6 @@ mod extra { } } - #[axum::async_trait] impl FromRequestParts for ParametersEx where S: Send + Sync, @@ -1198,12 +1208,12 @@ mod extra_typed_path { use validator::{Validate, ValidationError}; pub mod route { - pub const EXTRA_TYPED_PATH: &str = "/extra_typed_path/:v0/:v1"; - pub const EXTRA_TYPED_PATH_EX: &str = "/extra_typed_path_ex/:v0/:v1"; + pub const EXTRA_TYPED_PATH: &str = "/extra_typed_path/{v0}/{v1}"; + pub const EXTRA_TYPED_PATH_EX: &str = "/extra_typed_path_ex/{v0}/{v1}"; } #[derive(Validate, TypedPath, Deserialize)] - #[typed_path("/extra_typed_path/:v0/:v1")] + #[typed_path("/extra_typed_path/{v0}/{v1}")] pub struct TypedPathParam { #[validate(range(min = 5, max = 10))] v0: i32, @@ -1244,7 +1254,7 @@ mod extra_typed_path { } #[derive(Validate, TypedPath, Deserialize)] - #[typed_path("/extra_typed_path_ex/:v0/:v1")] + #[typed_path("/extra_typed_path_ex/{v0}/{v1}")] #[validate(context = TypedPathParamExValidationArguments)] pub struct TypedPathParamEx { #[validate(custom(function = "validate_v0", use_context))] diff --git a/src/validify.rs b/src/validify.rs index 2712e66..1ad3d8b 100644 --- a/src/validify.rs +++ b/src/validify.rs @@ -60,7 +60,10 @@ impl aide::OperationInput for Validated where T: aide::OperationInput, { - fn operation_input(ctx: &mut aide::gen::GenContext, operation: &mut aide::openapi::Operation) { + fn operation_input( + ctx: &mut aide::generate::GenContext, + operation: &mut aide::openapi::Operation, + ) { T::operation_input(ctx, operation); } } @@ -126,7 +129,10 @@ impl aide::OperationInput for Modified where T: aide::OperationInput, { - fn operation_input(ctx: &mut aide::gen::GenContext, operation: &mut aide::openapi::Operation) { + fn operation_input( + ctx: &mut aide::generate::GenContext, + operation: &mut aide::openapi::Operation, + ) { T::operation_input(ctx, operation); } } @@ -139,14 +145,14 @@ where type Inner = T::Inner; fn operation_response( - ctx: &mut aide::gen::GenContext, + ctx: &mut aide::generate::GenContext, operation: &mut aide::openapi::Operation, ) -> Option { T::operation_response(ctx, operation) } fn inferred_responses( - ctx: &mut aide::gen::GenContext, + ctx: &mut aide::generate::GenContext, operation: &mut aide::openapi::Operation, ) -> Vec<(Option, aide::openapi::Response)> { T::inferred_responses(ctx, operation) @@ -199,7 +205,10 @@ impl aide::OperationInput for Validified where T: aide::OperationInput, { - fn operation_input(ctx: &mut aide::gen::GenContext, operation: &mut aide::openapi::Operation) { + fn operation_input( + ctx: &mut aide::generate::GenContext, + operation: &mut aide::openapi::Operation, + ) { T::operation_input(ctx, operation); } } @@ -248,7 +257,10 @@ impl aide::OperationInput for ValidifiedByRef where T: aide::OperationInput, { - fn operation_input(ctx: &mut aide::gen::GenContext, operation: &mut aide::openapi::Operation) { + fn operation_input( + ctx: &mut aide::generate::GenContext, + operation: &mut aide::openapi::Operation, + ) { T::operation_input(ctx, operation); } } diff --git a/src/validify/test.rs b/src/validify/test.rs index 2430f16..d0799fe 100644 --- a/src/validify/test.rs +++ b/src/validify/test.rs @@ -1,4 +1,8 @@ +//! # Test for validify +//! + #![cfg(feature = "validify")] +#![allow(missing_docs)] use crate::tests::{ValidTest, ValidTestParameter}; use crate::{ @@ -19,6 +23,8 @@ use std::ops::Deref; use tokio::net::TcpListener; use validify::{Modify, Payload, Validate, Validify}; +/// ParametersValidify +/// #[derive(Debug, Clone, Deserialize, Serialize, Validify, Payload, Eq, PartialEq)] pub struct ParametersValidify { #[validate(range(min = 5.0, max = 10.0))] @@ -28,6 +34,8 @@ pub struct ParametersValidify { v1: String, } +/// ParametersValidifyWithoutPayload +/// #[derive(Clone, Validify, Eq, PartialEq)] #[cfg_attr(feature = "extra_protobuf", derive(Message))] #[cfg_attr( @@ -82,7 +90,7 @@ impl ValidTestParameter for ParametersValidify { } fn error() -> &'static [(&'static str, &'static str)] { - &[("not_v0_or_v1", "value")] + &[("v0", "not_a_number"), ("v1", "string")] } fn invalid() -> &'static Self { @@ -1110,6 +1118,8 @@ async fn test_main() -> anyhow::Result<()> { Ok(()) } +/// Test Executor +/// #[derive(Debug, Clone)] pub struct TestExecutor { client: reqwest::Client, @@ -1156,7 +1166,7 @@ impl TestExecutor { .await } - /// Execute all tests for `Modified` without validation + /// Execute all tests for `Validified` without validation pub async fn execute_validified( &self, method: Method, @@ -1166,7 +1176,7 @@ impl TestExecutor { method, route, StatusCode::OK, - T::INVALID_STATUS_CODE, + T::ERROR_STATUS_CODE, T::INVALID_STATUS_CODE, false, ) @@ -1230,6 +1240,7 @@ impl TestExecutor { Ok(()) } + /// Get reqwest client reference pub fn client(&self) -> &reqwest::Client { &self.client } @@ -1248,23 +1259,23 @@ pub async fn check_json(type_name: &'static str, response: reqwest::Response) { } mod route { - pub const PATH: &str = "/path/:v0/:v1"; - pub const PATH_MODIFIED: &str = "/path_modified/:v0/:v1"; - pub const PATH_VALIDIFIED: &str = "/path_validified/:v0/:v1"; - pub const PATH_VALIDIFIED_BY_REF: &str = "/path_validified_by_ref/:v0/:v1"; + pub const PATH: &str = "/path/{v0}/{v1}"; + pub const PATH_MODIFIED: &str = "/path_modified/{v0}/{v1}"; + pub const PATH_VALIDIFIED: &str = "/path_validified/{v0}/{v1}"; + pub const PATH_VALIDIFIED_BY_REF: &str = "/path_validified_by_ref/{v0}/{v1}"; pub const QUERY: &str = "/query"; - pub const QUERY_MODIFIED: &str = "/query_modified/:v0/:v1"; + pub const QUERY_MODIFIED: &str = "/query_modified/{v0}/{v1}"; - pub const QUERY_VALIDIFIED: &str = "/query_validified/:v0/:v1"; - pub const QUERY_VALIDIFIED_BY_REF: &str = "/query_validified_by_ref/:v0/:v1"; + pub const QUERY_VALIDIFIED: &str = "/query_validified/{v0}/{v1}"; + pub const QUERY_VALIDIFIED_BY_REF: &str = "/query_validified_by_ref/{v0}/{v1}"; pub const FORM: &str = "/form"; - pub const FORM_MODIFIED: &str = "/form_modified/:v0/:v1"; - pub const FORM_VALIDIFIED: &str = "/form_validified/:v0/:v1"; - pub const FORM_VALIDIFIED_BY_REF: &str = "/form_validified_by_ref/:v0/:v1"; + pub const FORM_MODIFIED: &str = "/form_modified/{v0}/{v1}"; + pub const FORM_VALIDIFIED: &str = "/form_validified/{v0}/{v1}"; + pub const FORM_VALIDIFIED_BY_REF: &str = "/form_validified_by_ref/{v0}/{v1}"; pub const JSON: &str = "/json"; - pub const JSON_MODIFIED: &str = "/json_modified/:v0/:v1"; - pub const JSON_VALIDIFIED: &str = "/json_validified/:v0/:v1"; - pub const JSON_VALIDIFIED_BY_REF: &str = "/json_validified_by_ref/:v0/:v1"; + pub const JSON_MODIFIED: &str = "/json_modified/{v0}/{v1}"; + pub const JSON_VALIDIFIED: &str = "/json_validified/{v0}/{v1}"; + pub const JSON_VALIDIFIED_BY_REF: &str = "/json_validified_by_ref/{v0}/{v1}"; } async fn extract_path( @@ -1602,7 +1613,7 @@ mod extra { } // 1.3. Implement your extractor (`FromRequestParts` or `FromRequest`) - #[axum::async_trait] + impl FromRequestParts for ParametersValidify where S: Send + Sync, @@ -1776,14 +1787,14 @@ mod extra_typed_path { use validify::{Validate, Validify}; pub mod route { - pub const EXTRA_TYPED_PATH: &str = "/extra_typed_path/:v0/:v1"; - pub const EXTRA_TYPED_PATH_MODIFIED: &str = "/extra_typed_path_modified/:v0/:v1"; + pub const EXTRA_TYPED_PATH: &str = "/extra_typed_path/{v0}/{v1}"; + pub const EXTRA_TYPED_PATH_MODIFIED: &str = "/extra_typed_path_modified/{v0}/{v1}"; pub const EXTRA_TYPED_PATH_VALIDIFIED_BY_REF: &str = - "/extra_typed_path_validified_by_ref/:v0/:v1"; + "/extra_typed_path_validified_by_ref/{v0}/{v1}"; } #[derive(Validate, TypedPath, Deserialize)] - #[typed_path("/extra_typed_path/:v0/:v1")] + #[typed_path("/extra_typed_path/{v0}/{v1}")] pub struct TypedPathParam { #[validate(range(min = 5.0, max = 10.0))] v0: i32, @@ -1800,7 +1811,7 @@ mod extra_typed_path { } #[derive(Validify, TypedPath, Deserialize, Clone, PartialEq, Eq)] - #[typed_path("/extra_typed_path_validified_by_ref/:v0/:v1")] + #[typed_path("/extra_typed_path_validified_by_ref/{v0}/{v1}")] pub struct TypedPathParamValidifiedByRef { #[validate(range(min = 5.0, max = 10.0))] v0: i32, @@ -1826,7 +1837,7 @@ mod extra_typed_path { } #[derive(Validify, TypedPath, Deserialize, Clone, PartialEq, Eq)] - #[typed_path("/extra_typed_path_modified/:v0/:v1")] + #[typed_path("/extra_typed_path_modified/{v0}/{v1}")] pub struct TypedPathParamModified { #[validate(range(min = 5.0, max = 10.0))] v0: i32, diff --git a/tests/custom.rs b/tests/custom.rs index 5fc8d61..c45986a 100644 --- a/tests/custom.rs +++ b/tests/custom.rs @@ -46,7 +46,7 @@ impl IntoResponse for MyDataRejection { } // 1.3. Implement your extractor (`FromRequestParts` or `FromRequest`) -#[axum::async_trait] + impl FromRequestParts for MyData where S: Send + Sync,