From 16283fd56255f2ef36e6a2fa1c4d5037b288369f Mon Sep 17 00:00:00 2001 From: gengteng Date: Sat, 6 Jan 2024 15:21:01 +0800 Subject: [PATCH] refactor: Validified --- Cargo.toml | 5 ++- src/extra/form.rs | 4 +-- src/extra/query.rs | 4 +-- src/form.rs | 4 +-- src/json.rs | 4 +-- src/msgpack.rs | 8 ++--- src/path.rs | 4 +-- src/query.rs | 4 +-- src/toml.rs | 4 +-- src/validify.rs | 27 +++++++-------- src/validify/test.rs | 80 ++++++++++++++++++++++++++++++++++---------- src/xml.rs | 4 +-- src/yaml.rs | 4 +-- 13 files changed, 100 insertions(+), 56 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b390d6e..67dc36d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,8 +28,7 @@ features = ["full", "aide"] axum = { version = "0.7.1", default-features = false } garde = { version = "0.16.3", optional = true } validator = { version = "0.16.1", optional = true} -validify = { version = "=1.0", optional = true } -validify_derive = { version = "=1.0", optional = true } +validify = { version = "1.3.0", optional = true} [dependencies.axum-extra] version = "0.9.0" @@ -74,7 +73,7 @@ default = ["basic", "validator"] basic = ["json", "form", "query"] garde = ["dep:garde"] validator = ["dep:validator"] -validify = ["dep:validify", "dep:validify_derive"] +validify = ["dep:validify"] json = ["axum/json"] form = ["axum/form"] query = ["axum/query"] diff --git a/src/extra/form.rs b/src/extra/form.rs index 2bf0946..197ce17 100644 --- a/src/extra/form.rs +++ b/src/extra/form.rs @@ -126,10 +126,10 @@ impl crate::PayloadExtractor for Form { } #[cfg(feature = "validify")] -impl crate::HasValidify for Form { +impl crate::HasValidify for Form { type Validify = T; type PayloadExtractor = Form; - fn from_validified(v: Self::Validify) -> Self { + fn from_validify(v: Self::Validify) -> Self { Form(v) } } diff --git a/src/extra/query.rs b/src/extra/query.rs index b53dfea..cce0939 100644 --- a/src/extra/query.rs +++ b/src/extra/query.rs @@ -126,11 +126,11 @@ impl crate::PayloadExtractor for Query { } #[cfg(feature = "validify")] -impl crate::HasValidify for Query { +impl crate::HasValidify for Query { type Validify = T; type PayloadExtractor = Query; - fn from_validified(v: Self::Validify) -> Self { + fn from_validify(v: Self::Validify) -> Self { Query(v) } } diff --git a/src/form.rs b/src/form.rs index 6f7e229..9aba12f 100644 --- a/src/form.rs +++ b/src/form.rs @@ -126,10 +126,10 @@ impl crate::PayloadExtractor for Form { } #[cfg(feature = "validify")] -impl crate::HasValidify for Form { +impl crate::HasValidify for Form { type Validify = T; type PayloadExtractor = Form; - fn from_validified(v: Self::Validify) -> Self { + fn from_validify(v: Self::Validify) -> Self { Form(v) } } diff --git a/src/json.rs b/src/json.rs index 628157e..9a01a3f 100644 --- a/src/json.rs +++ b/src/json.rs @@ -126,10 +126,10 @@ impl crate::PayloadExtractor for Json { } #[cfg(feature = "validify")] -impl crate::HasValidify for Json { +impl crate::HasValidify for Json { type Validify = T; type PayloadExtractor = Json; - fn from_validified(v: Self::Validify) -> Self { + fn from_validify(v: Self::Validify) -> Self { Json(v) } } diff --git a/src/msgpack.rs b/src/msgpack.rs index 1fb1e27..eacb6ec 100644 --- a/src/msgpack.rs +++ b/src/msgpack.rs @@ -133,10 +133,10 @@ impl crate::PayloadExtractor for MsgPack { } #[cfg(feature = "validify")] -impl crate::HasValidify for MsgPack { +impl crate::HasValidify for MsgPack { type Validify = T; type PayloadExtractor = MsgPack; - fn from_validified(v: Self::Validify) -> Self { + fn from_validify(v: Self::Validify) -> Self { MsgPack(v) } } @@ -175,10 +175,10 @@ impl crate::PayloadExtractor for MsgPackRaw { } #[cfg(feature = "validify")] -impl crate::HasValidify for MsgPackRaw { +impl crate::HasValidify for MsgPackRaw { type Validify = T; type PayloadExtractor = MsgPackRaw; - fn from_validified(v: Self::Validify) -> Self { + fn from_validify(v: Self::Validify) -> Self { MsgPackRaw(v) } } diff --git a/src/path.rs b/src/path.rs index f3fedd1..181b7ff 100644 --- a/src/path.rs +++ b/src/path.rs @@ -122,11 +122,11 @@ impl crate::PayloadExtractor for Path { } #[cfg(feature = "validify")] -impl crate::HasValidify for Path { +impl crate::HasValidify for Path { type Validify = T; type PayloadExtractor = Path; - fn from_validified(v: Self::Validify) -> Self { + fn from_validify(v: Self::Validify) -> Self { Path(v) } } diff --git a/src/query.rs b/src/query.rs index a909b69..1c1b115 100644 --- a/src/query.rs +++ b/src/query.rs @@ -126,11 +126,11 @@ impl crate::PayloadExtractor for Query { } #[cfg(feature = "validify")] -impl crate::HasValidify for Query { +impl crate::HasValidify for Query { type Validify = T; type PayloadExtractor = Query; - fn from_validified(v: Self::Validify) -> Self { + fn from_validify(v: Self::Validify) -> Self { Query(v) } } diff --git a/src/toml.rs b/src/toml.rs index 363113b..b53cb4b 100644 --- a/src/toml.rs +++ b/src/toml.rs @@ -126,10 +126,10 @@ impl crate::PayloadExtractor for Toml { } #[cfg(feature = "validify")] -impl crate::HasValidify for Toml { +impl crate::HasValidify for Toml { type Validify = T; type PayloadExtractor = Toml; - fn from_validified(v: Self::Validify) -> Self { + fn from_validify(v: Self::Validify) -> Self { Toml(v) } } diff --git a/src/validify.rs b/src/validify.rs index 4e4a830..43232e3 100644 --- a/src/validify.rs +++ b/src/validify.rs @@ -15,7 +15,7 @@ use axum::http::request::Parts; use axum::response::{IntoResponse, Response}; use std::fmt::{Display, Formatter}; use std::ops::{Deref, DerefMut}; -use validify::{Modify, Validate, ValidationErrors, Validify}; +use validify::{Modify, Validate, ValidationErrors, ValidifyPayload}; /// # `Validated` data extractor /// @@ -232,15 +232,15 @@ pub trait PayloadExtractor { /// pub trait HasValidify: Sized { /// Inner type that can be modified and validated using `validify`. - type Validify: Validify; + type Validify: ValidifyPayload; /// Extracts payload from the request, /// which will be used to construct the `Self::Validify` type /// and perform modification and validation on it. - type PayloadExtractor: PayloadExtractor::Payload>; + type PayloadExtractor: PayloadExtractor::Payload>; /// Re-packages the validified data back into the inner Extractor type. - fn from_validified(v: Self::Validify) -> Self; + fn from_validify(v: Self::Validify) -> Self; } #[async_trait] @@ -314,7 +314,6 @@ impl FromRequest for Validified where State: Send + Sync, Extractor: HasValidify, - Extractor::Validify: Validify, Extractor::PayloadExtractor: FromRequest, { type Rejection = @@ -323,10 +322,10 @@ where async fn from_request(req: Request, state: &State) -> Result { let payload = Extractor::PayloadExtractor::from_request(req, state) .await - .map_err(ValidifyRejection::Inner)?; - Ok(Validified(Extractor::from_validified( - Extractor::Validify::validify(payload.get_payload())?, - ))) + .map_err(ValidifyRejection::Inner)? + .get_payload(); + let validify = Extractor::Validify::validify_from(payload)?; + Ok(Validified(Extractor::from_validify(validify))) } } @@ -335,7 +334,6 @@ impl FromRequestParts for Validified where State: Send + Sync, Extractor: HasValidify, - Extractor::Validify: Validify, Extractor::PayloadExtractor: FromRequestParts, { type Rejection = @@ -344,10 +342,10 @@ where async fn from_request_parts(parts: &mut Parts, state: &State) -> Result { let payload = Extractor::PayloadExtractor::from_request_parts(parts, state) .await - .map_err(ValidifyRejection::Inner)?; - Ok(Validified(Extractor::from_validified( - Extractor::Validify::validify(payload.get_payload())?, - ))) + .map_err(ValidifyRejection::Inner)? + .get_payload(); + let validify = Extractor::Validify::validify_from(payload)?; + Ok(Validified(Extractor::from_validify(validify))) } } @@ -470,6 +468,7 @@ mod tests { #[test] fn modified_into_response() { + use validify::Validify; #[derive(Validify, Serialize)] struct Data { #[modify(trim)] diff --git a/src/validify/test.rs b/src/validify/test.rs index 4e5238b..51cd1dc 100644 --- a/src/validify/test.rs +++ b/src/validify/test.rs @@ -18,15 +18,24 @@ use std::any::type_name; use std::net::SocketAddr; use std::ops::Deref; use tokio::net::TcpListener; -use validify::{Modify, Validate, Validify}; +use validify::{Modify, Payload, Validate, Validify}; -#[derive(Clone, Deserialize, Serialize, Validify, Eq, PartialEq)] +#[derive(Debug, Clone, Deserialize, Serialize, Validify, Payload, Eq, PartialEq)] +pub struct ParametersValidify { + #[validate(range(min = 5.0, max = 10.0))] + v0: i32, + #[modify(lowercase)] + #[validate(length(min = 1, max = 10))] + v1: String, +} + +#[derive(Clone, Validify, Eq, PartialEq)] #[cfg_attr(feature = "extra_protobuf", derive(Message))] #[cfg_attr( feature = "typed_multipart", derive(axum_typed_multipart::TryFromMultipart) )] -pub struct ParametersValidify { +pub struct ParametersValidifyWithoutPayload { #[validate(range(min = 5.0, max = 10.0))] #[cfg_attr(feature = "extra_protobuf", prost(int32, tag = "1"))] v0: i32, @@ -56,6 +65,18 @@ static INVALID_PARAMETERS: Lazy = Lazy::new(|| ParametersVal v1: String::from("ABCDEFGHIJKLMN"), }); +static VALID_PARAMETERS_WITHOUT_PAYLOAD: Lazy = + Lazy::new(|| ParametersValidifyWithoutPayload { + v0: 5, + v1: String::from("ABCDEFG"), + }); + +static INVALID_PARAMETERS_WITHOUT_PAYLOAD: Lazy = + Lazy::new(|| ParametersValidifyWithoutPayload { + v0: 6, + v1: String::from("ABCDEFGHIJKLMN"), + }); + impl ValidTestParameter for ParametersValidify { fn valid() -> &'static Self { VALID_PARAMETERS.deref() @@ -70,6 +91,20 @@ impl ValidTestParameter for ParametersValidify { } } +impl ValidTestParameter for ParametersValidifyWithoutPayload { + fn valid() -> &'static Self { + VALID_PARAMETERS_WITHOUT_PAYLOAD.deref() + } + + fn error() -> &'static [(&'static str, &'static str)] { + &[("not_v0_or_v1", "value")] + } + + fn invalid() -> &'static Self { + INVALID_PARAMETERS_WITHOUT_PAYLOAD.deref() + } +} + impl HasValidate for ParametersValidify { type Validate = ParametersValidify; @@ -836,21 +871,21 @@ async fn test_main() -> anyhow::Result<()> { use axum_extra::protobuf::Protobuf; // Validated test_executor - .execute::>( + .execute::>( Method::POST, extra_protobuf::route::EXTRA_PROTOBUF, ) .await?; // Modified test_executor - .execute_modified::>( + .execute_modified::>( Method::POST, extra_protobuf::route::EXTRA_PROTOBUF_MODIFIED, ) .await?; // ValidifiedByRef test_executor - .execute::>( + .execute::>( Method::POST, extra_protobuf::route::EXTRA_PROTOBUF_VALIDIFIED_BY_REF, ) @@ -1356,7 +1391,10 @@ mod typed_header { #[cfg(feature = "typed_multipart")] mod typed_multipart { - use super::{check_modified, check_validated, check_validified, ParametersValidify}; + use super::{ + check_modified, check_validated, check_validified, ParametersValidify, + ParametersValidifyWithoutPayload, + }; use crate::{Modified, Validated, ValidifiedByRef}; use axum::http::StatusCode; use axum_typed_multipart::{BaseMultipart, TypedMultipart, TypedMultipartError}; @@ -1380,20 +1418,24 @@ mod typed_multipart { } pub(super) async fn extract_typed_multipart( - Validated(TypedMultipart(parameters)): Validated>, + Validated(TypedMultipart(parameters)): Validated< + TypedMultipart, + >, ) -> StatusCode { check_validated(¶meters) } pub(super) async fn extract_typed_multipart_modified( - Modified(TypedMultipart(parameters)): Modified>, + Modified(TypedMultipart(parameters)): Modified< + TypedMultipart, + >, ) -> StatusCode { check_modified(¶meters) } pub(super) async fn extract_typed_multipart_validified_by_ref( ValidifiedByRef(TypedMultipart(parameters)): ValidifiedByRef< - TypedMultipart, + TypedMultipart, >, ) -> StatusCode { check_validified(¶meters) @@ -1401,7 +1443,7 @@ mod typed_multipart { pub(super) async fn extract_base_multipart( Validated(BaseMultipart { data, .. }): Validated< - BaseMultipart, + BaseMultipart, >, ) -> StatusCode { check_validated(&data) @@ -1409,7 +1451,7 @@ mod typed_multipart { pub(super) async fn extract_base_multipart_modified( Modified(BaseMultipart { data, .. }): Modified< - BaseMultipart, + BaseMultipart, >, ) -> StatusCode { check_modified(&data) @@ -1417,7 +1459,7 @@ mod typed_multipart { pub(super) async fn extract_base_multipart_validified_by_ref( ValidifiedByRef(BaseMultipart { data, .. }): ValidifiedByRef< - BaseMultipart, + BaseMultipart, >, ) -> StatusCode { check_validified(&data) @@ -1813,7 +1855,9 @@ mod extra_form { #[cfg(feature = "extra_protobuf")] mod extra_protobuf { - use super::{check_modified, check_validated, check_validified, ParametersValidify}; + use super::{ + check_modified, check_validated, check_validified, ParametersValidifyWithoutPayload, + }; use crate::{Modified, Validated, ValidifiedByRef}; use axum::http::StatusCode; use axum_extra::protobuf::Protobuf; @@ -1825,19 +1869,21 @@ mod extra_protobuf { } pub async fn extract_extra_protobuf( - Validated(Protobuf(parameters)): Validated>, + Validated(Protobuf(parameters)): Validated>, ) -> StatusCode { check_validated(¶meters) } pub async fn extract_extra_protobuf_modified( - Modified(Protobuf(parameters)): Modified>, + Modified(Protobuf(parameters)): Modified>, ) -> StatusCode { check_modified(¶meters) } pub async fn extract_extra_protobuf_validified_by_ref( - ValidifiedByRef(Protobuf(parameters)): ValidifiedByRef>, + ValidifiedByRef(Protobuf(parameters)): ValidifiedByRef< + Protobuf, + >, ) -> StatusCode { check_validified(¶meters) } diff --git a/src/xml.rs b/src/xml.rs index 67acbf8..b28c08c 100644 --- a/src/xml.rs +++ b/src/xml.rs @@ -126,10 +126,10 @@ impl crate::PayloadExtractor for Xml { } #[cfg(feature = "validify")] -impl crate::HasValidify for Xml { +impl crate::HasValidify for Xml { type Validify = T; type PayloadExtractor = Xml; - fn from_validified(v: Self::Validify) -> Self { + fn from_validify(v: Self::Validify) -> Self { Xml(v) } } diff --git a/src/yaml.rs b/src/yaml.rs index 88f53b6..a0a9a6a 100644 --- a/src/yaml.rs +++ b/src/yaml.rs @@ -126,10 +126,10 @@ impl crate::PayloadExtractor for Yaml { } #[cfg(feature = "validify")] -impl crate::HasValidify for Yaml { +impl crate::HasValidify for Yaml { type Validify = T; type PayloadExtractor = Yaml; - fn from_validified(v: Self::Validify) -> Self { + fn from_validify(v: Self::Validify) -> Self { Yaml(v) } }