Compare commits

11 Commits

Author SHA1 Message Date
gengteng
a9533608bc dep: bump validify to 2.0.0
Some checks failed
CI / Test (push) Successful in 3m57s
CI / Format (push) Successful in 25s
CI / Clippy (push) Failing after 2m13s
CI / Coverage (push) Failing after 1m2s
2025-02-15 13:32:13 +08:00
gengteng
c603d48313 fix: clippy warninig 2025-01-25 21:41:15 +08:00
gengteng
cdec7d9b23 deps: bump axum to 0.8 2025-01-25 21:35:47 +08:00
GengTeng
73e5ef0876 Merge pull request #29 from MrAliSalehi/main
axum 0.8
2025-01-25 20:59:59 +08:00
qwxp
3f0e5aece3 Merge remote-tracking branch 'origin/main' 2025-01-02 16:00:31 +03:30
qwxp
0e924e6baf remove async_trait 2025-01-02 16:00:20 +03:30
qwxp
99aa6e0054 remove async_trait 2025-01-02 15:56:32 +03:30
qwxp
1f2d0419b4 upgrade axum, axum-extra and garde 2025-01-02 15:52:58 +03:30
gengteng
2ef8421875 feat: update axum-serde and axum_typed_multipart 2024-11-06 10:57:03 +08:00
GengTeng
1943a472bc Merge pull request #28 from gonzedge/gonzedge/validator-0-19-0
Upgrade validator to 0.19.0
2024-11-06 10:47:08 +08:00
Edgar Gonzalez
b76d4ef427 Upgrade validator to 0.19.0
So that we get the fix for validating struct with multiple members laid out in https://github.com/Keats/validator/issues/319, and fixed in https://github.com/Keats/validator/pull/321
2024-11-05 15:10:02 -05:00
11 changed files with 126 additions and 93 deletions

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "axum-valid" name = "axum-valid"
version = "0.20.0" version = "0.23.0"
description = "Provides validation extractors for your Axum application, allowing you to validate data using validator, garde, validify or all of them." description = "Provides validation extractors for your Axum application, allowing you to validate data using validator, garde, validify or all of them."
authors = ["GengTeng <me@gteng.org>"] authors = ["GengTeng <me@gteng.org>"]
license = "MIT" license = "MIT"
@@ -25,49 +25,49 @@ edition = "2021"
features = ["full", "aide"] features = ["full", "aide"]
[dependencies] [dependencies]
axum = { version = "0.7.5", default-features = false } axum = { version = "0.8", default-features = false }
garde = { version = "0.20.0", optional = true } garde = { version = "0.22.0", optional = true }
validator = { version = "0.18.1", optional = true } validator = { version = "0.20.0", optional = true }
validify = { version = "1.4.0", optional = true } validify = { version = "2.0.0", optional = true }
[dependencies.axum-extra] [dependencies.axum-extra]
version = "0.9.3" version = "0.10"
default-features = false default-features = false
optional = true optional = true
[dependencies.axum-serde] [dependencies.axum-serde]
version = "0.6.1" version = "0.8.1"
optional = true optional = true
[dependencies.axum_typed_multipart] [dependencies.axum_typed_multipart]
version = "0.12.1" version = "0.15.1"
optional = true optional = true
[dependencies.serde] [dependencies.serde]
version = "1.0.210" version = "1.0.217"
optional = true optional = true
[dependencies.aide] [dependencies.aide]
version = "0.13.4" version = "0.14.0"
optional = true optional = true
[dev-dependencies] [dev-dependencies]
anyhow = "1.0.87" anyhow = "1.0.87"
axum = { version = "0.7.5", features = ["macros"] } 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"] } reqwest = { version = "0.12.3", features = ["json", "multipart"] }
serde = { version = "1.0.195", features = ["derive"] } serde = { version = "1.0.195", features = ["derive"] }
validator = { version = "0.18.0", features = ["derive"] } validator = { version = "0.20.0", features = ["derive"] }
garde = { version = "0.20.0", features = ["serde", "derive"] } garde = { version = "0.22.0", features = ["serde", "derive"] }
serde_json = "1.0.108" serde_json = "1.0.108"
serde_yaml = "0.9.27" serde_yaml = "0.9.33"
quick-xml = { version = "0.36.1", features = ["serialize"] } quick-xml = { version = "0.37.1", features = ["serialize"] }
ciborium = { version = "0.2.2" } ciborium = { version = "0.2.2" }
toml = "0.8.8" toml = "0.8.14"
mime = "0.3.17" mime = "0.3.17"
prost = "0.12.3" prost = "0.13.4"
once_cell = "1.18.0" once_cell = "1.20.2"
rmp-serde = "1.1.2" rmp-serde = "1.3.0"
[features] [features]
default = ["basic", "validator"] default = ["basic", "validator"]

View File

@@ -61,7 +61,6 @@
//! } //! }
//! } //! }
//! //!
//! #[axum::async_trait]
//! impl<S> FromRequestParts<S> for Parameter //! impl<S> FromRequestParts<S> for Parameter
//! where //! where
//! S: Send + Sync, //! S: Send + Sync,
@@ -108,7 +107,7 @@
//! } //! }
//! } //! }
//! //!
//! #[axum::async_trait] //!
//! impl<S> FromRequestParts<S> for Parameter //! impl<S> FromRequestParts<S> for Parameter
//! where //! where
//! S: Send + Sync, //! S: Send + Sync,
@@ -189,7 +188,7 @@
//! } //! }
//! } //! }
//! //!
//! #[axum::async_trait] //!
//! impl<S> FromRequestParts<S> for Parameter //! impl<S> FromRequestParts<S> for Parameter
//! where //! where
//! S: Send + Sync, //! S: Send + Sync,
@@ -242,7 +241,7 @@
//! } //! }
//! } //! }
//! //!
//! #[axum::async_trait] //!
//! impl<S> FromRequestParts<S> for Parameter //! impl<S> FromRequestParts<S> for Parameter
//! where //! where
//! S: Send + Sync, //! S: Send + Sync,
@@ -332,7 +331,7 @@
//! } //! }
//! } //! }
//! //!
//! #[axum::async_trait] //!
//! impl<S> FromRequestParts<S> for Parameter //! impl<S> FromRequestParts<S> for Parameter
//! where //! where
//! S: Send + Sync, //! S: Send + Sync,
@@ -407,7 +406,7 @@
//! } //! }
//! } //! }
//! //!
//! #[axum::async_trait] //!
//! impl<S> FromRequestParts<S> for Parameter //! impl<S> FromRequestParts<S> for Parameter
//! where //! where
//! S: Send + Sync, //! S: Send + Sync,

View File

@@ -143,7 +143,7 @@ mod tests {
use serde::Serialize; use serde::Serialize;
impl<T: ValidTestParameter + Serialize> ValidTest for Form<T> { impl<T: ValidTestParameter + Serialize> ValidTest for Form<T> {
const ERROR_STATUS_CODE: StatusCode = StatusCode::BAD_REQUEST; const ERROR_STATUS_CODE: StatusCode = StatusCode::UNPROCESSABLE_ENTITY;
fn set_valid_request(builder: RequestBuilder) -> RequestBuilder { fn set_valid_request(builder: RequestBuilder) -> RequestBuilder {
builder.form(T::valid()) builder.form(T::valid())

View File

@@ -29,7 +29,7 @@
//! } //! }
//! //!
//! #[derive(TypedPath, Deserialize, Validate)] //! #[derive(TypedPath, Deserialize, Validate)]
//! #[typed_path("/extra_typed_path/:v0/:v1")] //! #[typed_path("/extra_typed_path/{v0}/{v1}")]
//! struct Parameter { //! struct Parameter {
//! #[validate(range(min = 5, max = 10))] //! #[validate(range(min = 5, max = 10))]
//! v0: i32, //! v0: i32,
@@ -63,7 +63,7 @@
//! } //! }
//! //!
//! #[derive(TypedPath, Deserialize, Validate)] //! #[derive(TypedPath, Deserialize, Validate)]
//! #[typed_path("/extra_typed_path/:v0/:v1")] //! #[typed_path("/extra_typed_path/{v0}/{v1}")]
//! struct Parameter { //! struct Parameter {
//! #[garde(range(min = 5, max = 10))] //! #[garde(range(min = 5, max = 10))]
//! v0: i32, //! v0: i32,

View File

@@ -9,7 +9,6 @@
pub mod test; pub mod test;
use crate::{HasValidate, ValidationRejection}; use crate::{HasValidate, ValidationRejection};
use axum::async_trait;
use axum::extract::{FromRef, FromRequest, FromRequestParts, Request}; use axum::extract::{FromRef, FromRequest, FromRequestParts, Request};
use axum::http::request::Parts; use axum::http::request::Parts;
use garde::{Report, Validate}; use garde::{Report, Validate};
@@ -62,7 +61,10 @@ impl<T> aide::OperationInput for Garde<T>
where where
T: aide::OperationInput, 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); T::operation_input(ctx, operation);
} }
} }
@@ -77,7 +79,6 @@ impl<E> From<Report> for GardeRejection<E> {
} }
} }
#[async_trait]
impl<State, Extractor, Context> FromRequest<State> for Garde<Extractor> impl<State, Extractor, Context> FromRequest<State> for Garde<Extractor>
where where
State: Send + Sync, State: Send + Sync,
@@ -98,7 +99,6 @@ where
} }
} }
#[async_trait]
impl<State, Extractor, Context> FromRequestParts<State> for Garde<Extractor> impl<State, Extractor, Context> FromRequestParts<State> for Garde<Extractor>
where where
State: Send + Sync, State: Send + Sync,

View File

@@ -1,3 +1,6 @@
//! # Test for garde
//!
#![cfg(feature = "garde")] #![cfg(feature = "garde")]
use crate::tests::{ValidTest, ValidTestParameter}; use crate::tests::{ValidTest, ValidTestParameter};
@@ -15,6 +18,8 @@ use std::net::SocketAddr;
use std::ops::Deref; use std::ops::Deref;
use tokio::net::TcpListener; use tokio::net::TcpListener;
/// ParametersGarde
///
#[derive(Clone, Deserialize, Serialize, Validate, Eq, PartialEq)] #[derive(Clone, Deserialize, Serialize, Validate, Eq, PartialEq)]
#[cfg_attr(feature = "extra_protobuf", derive(prost::Message))] #[cfg_attr(feature = "extra_protobuf", derive(prost::Message))]
#[cfg_attr( #[cfg_attr(
@@ -434,6 +439,8 @@ async fn test_main() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
/// Test Executor
///
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct TestExecutor { pub struct TestExecutor {
client: reqwest::Client, client: reqwest::Client,
@@ -496,6 +503,7 @@ impl TestExecutor {
Ok(()) Ok(())
} }
/// Get reqwest client reference
pub fn client(&self) -> &reqwest::Client { pub fn client(&self) -> &reqwest::Client {
&self.client &self.client
} }
@@ -514,7 +522,7 @@ pub async fn check_json(type_name: &'static str, response: reqwest::Response) {
} }
mod route { mod route {
pub const PATH: &str = "/path/:v0/:v1"; pub const PATH: &str = "/path/{v0}/{v1}";
pub const QUERY: &str = "/query"; pub const QUERY: &str = "/query";
pub const FORM: &str = "/form"; pub const FORM: &str = "/form";
pub const JSON: &str = "/json"; pub const JSON: &str = "/json";
@@ -692,7 +700,7 @@ mod extra {
} }
// 1.3. Implement your extractor (`FromRequestParts` or `FromRequest`) // 1.3. Implement your extractor (`FromRequestParts` or `FromRequest`)
#[axum::async_trait]
impl<S> FromRequestParts<S> for ParametersGarde impl<S> FromRequestParts<S> for ParametersGarde
where where
S: Send + Sync, S: Send + Sync,
@@ -812,11 +820,11 @@ mod extra_typed_path {
use serde::Deserialize; use serde::Deserialize;
pub mod route { 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)] #[derive(Validate, TypedPath, Deserialize)]
#[typed_path("/extra_typed_path/:v0/:v1")] #[typed_path("/extra_typed_path/{v0}/{v1}")]
pub struct TypedPathParam { pub struct TypedPathParam {
#[garde(range(min = 5, max = 10))] #[garde(range(min = 5, max = 10))]
v0: i32, v0: i32,

View File

@@ -9,7 +9,6 @@
pub mod test; pub mod test;
use crate::{HasValidate, ValidationRejection}; use crate::{HasValidate, ValidationRejection};
use axum::async_trait;
use axum::extract::{FromRef, FromRequest, FromRequestParts, Request}; use axum::extract::{FromRef, FromRequest, FromRequestParts, Request};
use axum::http::request::Parts; use axum::http::request::Parts;
use std::fmt::Display; use std::fmt::Display;
@@ -62,7 +61,10 @@ impl<T> aide::OperationInput for Valid<T>
where where
T: aide::OperationInput, 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); T::operation_input(ctx, operation);
} }
} }
@@ -118,7 +120,10 @@ impl<T> aide::OperationInput for ValidEx<T>
where where
T: aide::OperationInput, 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); T::operation_input(ctx, operation);
} }
} }
@@ -144,7 +149,6 @@ pub trait HasValidateArgs<'v> {
fn get_validate_args(&self) -> &Self::ValidateArgs; fn get_validate_args(&self) -> &Self::ValidateArgs;
} }
#[async_trait]
impl<State, Extractor> FromRequest<State> for Valid<Extractor> impl<State, Extractor> FromRequest<State> for Valid<Extractor>
where where
State: Send + Sync, State: Send + Sync,
@@ -162,7 +166,6 @@ where
} }
} }
#[async_trait]
impl<State, Extractor> FromRequestParts<State> for Valid<Extractor> impl<State, Extractor> FromRequestParts<State> for Valid<Extractor>
where where
State: Send + Sync, State: Send + Sync,
@@ -180,7 +183,6 @@ where
} }
} }
#[async_trait]
impl<State, Extractor, Args> FromRequest<State> for ValidEx<Extractor> impl<State, Extractor, Args> FromRequest<State> for ValidEx<Extractor>
where where
State: Send + Sync, State: Send + Sync,
@@ -201,7 +203,6 @@ where
} }
} }
#[async_trait]
impl<State, Extractor, Args> FromRequestParts<State> for ValidEx<Extractor> impl<State, Extractor, Args> FromRequestParts<State> for ValidEx<Extractor>
where where
State: Send + Sync, State: Send + Sync,
@@ -221,6 +222,7 @@ where
} }
} }
/// basic tests for validator
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use super::*; use super::*;

View File

@@ -1,3 +1,6 @@
//! # Test for validator
//!
#![cfg(feature = "validator")] #![cfg(feature = "validator")]
use crate::tests::{ValidTest, ValidTestParameter}; use crate::tests::{ValidTest, ValidTestParameter};
@@ -16,6 +19,8 @@ use std::sync::Arc;
use tokio::net::TcpListener; use tokio::net::TcpListener;
use validator::{Validate, ValidateArgs, ValidationError}; use validator::{Validate, ValidateArgs, ValidationError};
/// Parameters
///
#[derive(Clone, Deserialize, Serialize, Validate, Eq, PartialEq)] #[derive(Clone, Deserialize, Serialize, Validate, Eq, PartialEq)]
#[cfg_attr(feature = "extra_protobuf", derive(prost::Message))] #[cfg_attr(feature = "extra_protobuf", derive(prost::Message))]
#[cfg_attr( #[cfg_attr(
@@ -31,6 +36,8 @@ pub struct Parameters {
v1: String, v1: String,
} }
/// ParametersEx
///
#[derive(Clone, Deserialize, Serialize, Validate, Eq, PartialEq)] #[derive(Clone, Deserialize, Serialize, Validate, Eq, PartialEq)]
#[cfg_attr(feature = "extra_protobuf", derive(prost::Message))] #[cfg_attr(feature = "extra_protobuf", derive(prost::Message))]
#[cfg_attr( #[cfg_attr(
@@ -69,6 +76,8 @@ struct ParametersExValidationArgumentsInner {
v1_length_range: RangeInclusive<usize>, v1_length_range: RangeInclusive<usize>,
} }
/// ParametersExValidationArguments
///
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct ParametersExValidationArguments { pub struct ParametersExValidationArguments {
inner: Arc<ParametersExValidationArgumentsInner>, inner: Arc<ParametersExValidationArgumentsInner>,
@@ -115,7 +124,7 @@ impl HasValidate for Parameters {
} }
} }
impl<'v> HasValidateArgs<'v> for ParametersEx { impl HasValidateArgs<'_> for ParametersEx {
type ValidateArgs = ParametersEx; type ValidateArgs = ParametersEx;
fn get_validate_args(&self) -> &Self::ValidateArgs { fn get_validate_args(&self) -> &Self::ValidateArgs {
@@ -663,6 +672,7 @@ async fn test_main() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
/// Test Executor
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct TestExecutor { pub struct TestExecutor {
client: reqwest::Client, client: reqwest::Client,
@@ -725,6 +735,7 @@ impl TestExecutor {
Ok(()) Ok(())
} }
/// Get reqwest client reference
pub fn client(&self) -> &reqwest::Client { pub fn client(&self) -> &reqwest::Client {
&self.client &self.client
} }
@@ -743,8 +754,8 @@ pub async fn check_json(type_name: &'static str, response: reqwest::Response) {
} }
mod route { mod route {
pub const PATH: &str = "/path/:v0/:v1"; pub const PATH: &str = "/path/{v0}/{v1}";
pub const PATH_EX: &str = "/path_ex/:v0/:v1"; pub const PATH_EX: &str = "/path_ex/{v0}/{v1}";
pub const QUERY: &str = "/query"; pub const QUERY: &str = "/query";
pub const QUERY_EX: &str = "/query_ex"; pub const QUERY_EX: &str = "/query_ex";
pub const FORM: &str = "/form"; pub const FORM: &str = "/form";
@@ -1036,7 +1047,7 @@ mod extra {
} }
// 1.3. Implement your extractor (`FromRequestParts` or `FromRequest`) // 1.3. Implement your extractor (`FromRequestParts` or `FromRequest`)
#[axum::async_trait]
impl<S> FromRequestParts<S> for Parameters impl<S> FromRequestParts<S> for Parameters
where where
S: Send + Sync, S: Send + Sync,
@@ -1052,7 +1063,6 @@ mod extra {
} }
} }
#[axum::async_trait]
impl<S> FromRequestParts<S> for ParametersEx impl<S> FromRequestParts<S> for ParametersEx
where where
S: Send + Sync, S: Send + Sync,
@@ -1198,12 +1208,12 @@ mod extra_typed_path {
use validator::{Validate, ValidationError}; use validator::{Validate, ValidationError};
pub mod route { 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}";
pub const EXTRA_TYPED_PATH_EX: &str = "/extra_typed_path_ex/:v0/:v1"; pub const EXTRA_TYPED_PATH_EX: &str = "/extra_typed_path_ex/{v0}/{v1}";
} }
#[derive(Validate, TypedPath, Deserialize)] #[derive(Validate, TypedPath, Deserialize)]
#[typed_path("/extra_typed_path/:v0/:v1")] #[typed_path("/extra_typed_path/{v0}/{v1}")]
pub struct TypedPathParam { pub struct TypedPathParam {
#[validate(range(min = 5, max = 10))] #[validate(range(min = 5, max = 10))]
v0: i32, v0: i32,
@@ -1244,7 +1254,7 @@ mod extra_typed_path {
} }
#[derive(Validate, TypedPath, Deserialize)] #[derive(Validate, TypedPath, Deserialize)]
#[typed_path("/extra_typed_path_ex/:v0/:v1")] #[typed_path("/extra_typed_path_ex/{v0}/{v1}")]
#[validate(context = TypedPathParamExValidationArguments)] #[validate(context = TypedPathParamExValidationArguments)]
pub struct TypedPathParamEx { pub struct TypedPathParamEx {
#[validate(custom(function = "validate_v0", use_context))] #[validate(custom(function = "validate_v0", use_context))]
@@ -1253,7 +1263,7 @@ mod extra_typed_path {
v1: String, v1: String,
} }
impl<'v> HasValidateArgs<'v> for TypedPathParamEx { impl HasValidateArgs<'_> for TypedPathParamEx {
type ValidateArgs = Self; type ValidateArgs = Self;
fn get_validate_args(&self) -> &Self::ValidateArgs { fn get_validate_args(&self) -> &Self::ValidateArgs {

View File

@@ -9,7 +9,6 @@
pub mod test; pub mod test;
use crate::{HasValidate, ValidationRejection}; use crate::{HasValidate, ValidationRejection};
use axum::async_trait;
use axum::extract::{FromRequest, FromRequestParts, Request}; use axum::extract::{FromRequest, FromRequestParts, Request};
use axum::http::request::Parts; use axum::http::request::Parts;
use axum::response::{IntoResponse, Response}; use axum::response::{IntoResponse, Response};
@@ -61,7 +60,10 @@ impl<T> aide::OperationInput for Validated<T>
where where
T: aide::OperationInput, 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); T::operation_input(ctx, operation);
} }
} }
@@ -127,7 +129,10 @@ impl<T> aide::OperationInput for Modified<T>
where where
T: aide::OperationInput, 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); T::operation_input(ctx, operation);
} }
} }
@@ -140,14 +145,14 @@ where
type Inner = T::Inner; type Inner = T::Inner;
fn operation_response( fn operation_response(
ctx: &mut aide::gen::GenContext, ctx: &mut aide::generate::GenContext,
operation: &mut aide::openapi::Operation, operation: &mut aide::openapi::Operation,
) -> Option<aide::openapi::Response> { ) -> Option<aide::openapi::Response> {
T::operation_response(ctx, operation) T::operation_response(ctx, operation)
} }
fn inferred_responses( fn inferred_responses(
ctx: &mut aide::gen::GenContext, ctx: &mut aide::generate::GenContext,
operation: &mut aide::openapi::Operation, operation: &mut aide::openapi::Operation,
) -> Vec<(Option<u16>, aide::openapi::Response)> { ) -> Vec<(Option<u16>, aide::openapi::Response)> {
T::inferred_responses(ctx, operation) T::inferred_responses(ctx, operation)
@@ -200,7 +205,10 @@ impl<T> aide::OperationInput for Validified<T>
where where
T: aide::OperationInput, 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); T::operation_input(ctx, operation);
} }
} }
@@ -249,7 +257,10 @@ impl<T> aide::OperationInput for ValidifiedByRef<T>
where where
T: aide::OperationInput, 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); T::operation_input(ctx, operation);
} }
} }
@@ -301,7 +312,6 @@ pub trait HasValidify: Sized {
fn from_validify(v: Self::Validify) -> Self; fn from_validify(v: Self::Validify) -> Self;
} }
#[async_trait]
impl<State, Extractor> FromRequest<State> for Validated<Extractor> impl<State, Extractor> FromRequest<State> for Validated<Extractor>
where where
State: Send + Sync, State: Send + Sync,
@@ -319,7 +329,6 @@ where
} }
} }
#[async_trait]
impl<State, Extractor> FromRequestParts<State> for Validated<Extractor> impl<State, Extractor> FromRequestParts<State> for Validated<Extractor>
where where
State: Send + Sync, State: Send + Sync,
@@ -337,7 +346,6 @@ where
} }
} }
#[async_trait]
impl<State, Extractor> FromRequest<State> for Modified<Extractor> impl<State, Extractor> FromRequest<State> for Modified<Extractor>
where where
State: Send + Sync, State: Send + Sync,
@@ -352,7 +360,6 @@ where
} }
} }
#[async_trait]
impl<State, Extractor> FromRequestParts<State> for Modified<Extractor> impl<State, Extractor> FromRequestParts<State> for Modified<Extractor>
where where
State: Send + Sync, State: Send + Sync,
@@ -367,7 +374,6 @@ where
} }
} }
#[async_trait]
impl<State, Extractor> FromRequest<State> for Validified<Extractor> impl<State, Extractor> FromRequest<State> for Validified<Extractor>
where where
State: Send + Sync, State: Send + Sync,
@@ -387,7 +393,6 @@ where
} }
} }
#[async_trait]
impl<State, Extractor> FromRequestParts<State> for Validified<Extractor> impl<State, Extractor> FromRequestParts<State> for Validified<Extractor>
where where
State: Send + Sync, State: Send + Sync,
@@ -407,7 +412,6 @@ where
} }
} }
#[async_trait]
impl<State, Extractor> FromRequest<State> for ValidifiedByRef<Extractor> impl<State, Extractor> FromRequest<State> for ValidifiedByRef<Extractor>
where where
State: Send + Sync, State: Send + Sync,
@@ -426,7 +430,6 @@ where
} }
} }
#[async_trait]
impl<State, Extractor> FromRequestParts<State> for ValidifiedByRef<Extractor> impl<State, Extractor> FromRequestParts<State> for ValidifiedByRef<Extractor>
where where
State: Send + Sync, State: Send + Sync,

View File

@@ -1,4 +1,8 @@
//! # Test for validify
//!
#![cfg(feature = "validify")] #![cfg(feature = "validify")]
#![allow(missing_docs)]
use crate::tests::{ValidTest, ValidTestParameter}; use crate::tests::{ValidTest, ValidTestParameter};
use crate::{ use crate::{
@@ -19,6 +23,8 @@ use std::ops::Deref;
use tokio::net::TcpListener; use tokio::net::TcpListener;
use validify::{Modify, Payload, Validate, Validify}; use validify::{Modify, Payload, Validate, Validify};
/// ParametersValidify
///
#[derive(Debug, Clone, Deserialize, Serialize, Validify, Payload, Eq, PartialEq)] #[derive(Debug, Clone, Deserialize, Serialize, Validify, Payload, Eq, PartialEq)]
pub struct ParametersValidify { pub struct ParametersValidify {
#[validate(range(min = 5.0, max = 10.0))] #[validate(range(min = 5.0, max = 10.0))]
@@ -28,6 +34,8 @@ pub struct ParametersValidify {
v1: String, v1: String,
} }
/// ParametersValidifyWithoutPayload
///
#[derive(Clone, Validify, Eq, PartialEq)] #[derive(Clone, Validify, Eq, PartialEq)]
#[cfg_attr(feature = "extra_protobuf", derive(Message))] #[cfg_attr(feature = "extra_protobuf", derive(Message))]
#[cfg_attr( #[cfg_attr(
@@ -82,7 +90,7 @@ impl ValidTestParameter for ParametersValidify {
} }
fn error() -> &'static [(&'static str, &'static str)] { fn error() -> &'static [(&'static str, &'static str)] {
&[("not_v0_or_v1", "value")] &[("v0", "not_a_number"), ("v1", "string")]
} }
fn invalid() -> &'static Self { fn invalid() -> &'static Self {
@@ -1110,6 +1118,8 @@ async fn test_main() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
/// Test Executor
///
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct TestExecutor { pub struct TestExecutor {
client: reqwest::Client, client: reqwest::Client,
@@ -1156,7 +1166,7 @@ impl TestExecutor {
.await .await
} }
/// Execute all tests for `Modified` without validation /// Execute all tests for `Validified` without validation
pub async fn execute_validified<T: ValidTest>( pub async fn execute_validified<T: ValidTest>(
&self, &self,
method: Method, method: Method,
@@ -1166,7 +1176,7 @@ impl TestExecutor {
method, method,
route, route,
StatusCode::OK, StatusCode::OK,
T::INVALID_STATUS_CODE, T::ERROR_STATUS_CODE,
T::INVALID_STATUS_CODE, T::INVALID_STATUS_CODE,
false, false,
) )
@@ -1230,6 +1240,7 @@ impl TestExecutor {
Ok(()) Ok(())
} }
/// Get reqwest client reference
pub fn client(&self) -> &reqwest::Client { pub fn client(&self) -> &reqwest::Client {
&self.client &self.client
} }
@@ -1248,23 +1259,23 @@ pub async fn check_json(type_name: &'static str, response: reqwest::Response) {
} }
mod route { mod route {
pub const PATH: &str = "/path/:v0/:v1"; pub const PATH: &str = "/path/{v0}/{v1}";
pub const PATH_MODIFIED: &str = "/path_modified/:v0/:v1"; pub const PATH_MODIFIED: &str = "/path_modified/{v0}/{v1}";
pub const PATH_VALIDIFIED: &str = "/path_validified/: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_VALIDIFIED_BY_REF: &str = "/path_validified_by_ref/{v0}/{v1}";
pub const QUERY: &str = "/query"; 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: &str = "/query_validified/{v0}/{v1}";
pub const QUERY_VALIDIFIED_BY_REF: &str = "/query_validified_by_ref/:v0/:v1"; pub const QUERY_VALIDIFIED_BY_REF: &str = "/query_validified_by_ref/{v0}/{v1}";
pub const FORM: &str = "/form"; pub const FORM: &str = "/form";
pub const FORM_MODIFIED: &str = "/form_modified/:v0/:v1"; pub const FORM_MODIFIED: &str = "/form_modified/{v0}/{v1}";
pub const FORM_VALIDIFIED: &str = "/form_validified/: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_VALIDIFIED_BY_REF: &str = "/form_validified_by_ref/{v0}/{v1}";
pub const JSON: &str = "/json"; pub const JSON: &str = "/json";
pub const JSON_MODIFIED: &str = "/json_modified/:v0/:v1"; pub const JSON_MODIFIED: &str = "/json_modified/{v0}/{v1}";
pub const JSON_VALIDIFIED: &str = "/json_validified/: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_VALIDIFIED_BY_REF: &str = "/json_validified_by_ref/{v0}/{v1}";
} }
async fn extract_path( async fn extract_path(
@@ -1602,7 +1613,7 @@ mod extra {
} }
// 1.3. Implement your extractor (`FromRequestParts` or `FromRequest`) // 1.3. Implement your extractor (`FromRequestParts` or `FromRequest`)
#[axum::async_trait]
impl<S> FromRequestParts<S> for ParametersValidify impl<S> FromRequestParts<S> for ParametersValidify
where where
S: Send + Sync, S: Send + Sync,
@@ -1776,14 +1787,14 @@ mod extra_typed_path {
use validify::{Validate, Validify}; use validify::{Validate, Validify};
pub mod route { 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}";
pub const EXTRA_TYPED_PATH_MODIFIED: &str = "/extra_typed_path_modified/:v0/:v1"; pub const EXTRA_TYPED_PATH_MODIFIED: &str = "/extra_typed_path_modified/{v0}/{v1}";
pub const EXTRA_TYPED_PATH_VALIDIFIED_BY_REF: &str = 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)] #[derive(Validate, TypedPath, Deserialize)]
#[typed_path("/extra_typed_path/:v0/:v1")] #[typed_path("/extra_typed_path/{v0}/{v1}")]
pub struct TypedPathParam { pub struct TypedPathParam {
#[validate(range(min = 5.0, max = 10.0))] #[validate(range(min = 5.0, max = 10.0))]
v0: i32, v0: i32,
@@ -1800,7 +1811,7 @@ mod extra_typed_path {
} }
#[derive(Validify, TypedPath, Deserialize, Clone, PartialEq, Eq)] #[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 { pub struct TypedPathParamValidifiedByRef {
#[validate(range(min = 5.0, max = 10.0))] #[validate(range(min = 5.0, max = 10.0))]
v0: i32, v0: i32,
@@ -1826,7 +1837,7 @@ mod extra_typed_path {
} }
#[derive(Validify, TypedPath, Deserialize, Clone, PartialEq, Eq)] #[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 { pub struct TypedPathParamModified {
#[validate(range(min = 5.0, max = 10.0))] #[validate(range(min = 5.0, max = 10.0))]
v0: i32, v0: i32,

View File

@@ -46,7 +46,7 @@ impl IntoResponse for MyDataRejection {
} }
// 1.3. Implement your extractor (`FromRequestParts` or `FromRequest`) // 1.3. Implement your extractor (`FromRequestParts` or `FromRequest`)
#[axum::async_trait]
impl<S> FromRequestParts<S> for MyData impl<S> FromRequestParts<S> for MyData
where where
S: Send + Sync, S: Send + Sync,