refactor: Validified
This commit is contained in:
@@ -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"]
|
||||
|
||||
@@ -126,10 +126,10 @@ impl<T> crate::PayloadExtractor for Form<T> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "validify")]
|
||||
impl<T: validify::Validify> crate::HasValidify for Form<T> {
|
||||
impl<T: validify::Validify + validify::ValidifyPayload> crate::HasValidify for Form<T> {
|
||||
type Validify = T;
|
||||
type PayloadExtractor = Form<T::Payload>;
|
||||
fn from_validified(v: Self::Validify) -> Self {
|
||||
fn from_validify(v: Self::Validify) -> Self {
|
||||
Form(v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,11 +126,11 @@ impl<T> crate::PayloadExtractor for Query<T> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "validify")]
|
||||
impl<T: validify::Validify> crate::HasValidify for Query<T> {
|
||||
impl<T: validify::Validify + validify::ValidifyPayload> crate::HasValidify for Query<T> {
|
||||
type Validify = T;
|
||||
type PayloadExtractor = Query<T::Payload>;
|
||||
|
||||
fn from_validified(v: Self::Validify) -> Self {
|
||||
fn from_validify(v: Self::Validify) -> Self {
|
||||
Query(v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,10 +126,10 @@ impl<T> crate::PayloadExtractor for Form<T> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "validify")]
|
||||
impl<T: validify::Validify> crate::HasValidify for Form<T> {
|
||||
impl<T: validify::Validify + validify::ValidifyPayload> crate::HasValidify for Form<T> {
|
||||
type Validify = T;
|
||||
type PayloadExtractor = Form<T::Payload>;
|
||||
fn from_validified(v: Self::Validify) -> Self {
|
||||
fn from_validify(v: Self::Validify) -> Self {
|
||||
Form(v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,10 +126,10 @@ impl<T> crate::PayloadExtractor for Json<T> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "validify")]
|
||||
impl<T: validify::Validify> crate::HasValidify for Json<T> {
|
||||
impl<T: validify::Validify + validify::ValidifyPayload> crate::HasValidify for Json<T> {
|
||||
type Validify = T;
|
||||
type PayloadExtractor = Json<T::Payload>;
|
||||
fn from_validified(v: Self::Validify) -> Self {
|
||||
fn from_validify(v: Self::Validify) -> Self {
|
||||
Json(v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,10 +133,10 @@ impl<T> crate::PayloadExtractor for MsgPack<T> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "validify")]
|
||||
impl<T: validify::Validify> crate::HasValidify for MsgPack<T> {
|
||||
impl<T: validify::Validify + validify::ValidifyPayload> crate::HasValidify for MsgPack<T> {
|
||||
type Validify = T;
|
||||
type PayloadExtractor = MsgPack<T::Payload>;
|
||||
fn from_validified(v: Self::Validify) -> Self {
|
||||
fn from_validify(v: Self::Validify) -> Self {
|
||||
MsgPack(v)
|
||||
}
|
||||
}
|
||||
@@ -175,10 +175,10 @@ impl<T> crate::PayloadExtractor for MsgPackRaw<T> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "validify")]
|
||||
impl<T: validify::Validify> crate::HasValidify for MsgPackRaw<T> {
|
||||
impl<T: validify::Validify + validify::ValidifyPayload> crate::HasValidify for MsgPackRaw<T> {
|
||||
type Validify = T;
|
||||
type PayloadExtractor = MsgPackRaw<T::Payload>;
|
||||
fn from_validified(v: Self::Validify) -> Self {
|
||||
fn from_validify(v: Self::Validify) -> Self {
|
||||
MsgPackRaw(v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,11 +122,11 @@ impl<T> crate::PayloadExtractor for Path<T> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "validify")]
|
||||
impl<T: validify::Validify> crate::HasValidify for Path<T> {
|
||||
impl<T: validify::Validify + validify::ValidifyPayload> crate::HasValidify for Path<T> {
|
||||
type Validify = T;
|
||||
type PayloadExtractor = Path<T::Payload>;
|
||||
|
||||
fn from_validified(v: Self::Validify) -> Self {
|
||||
fn from_validify(v: Self::Validify) -> Self {
|
||||
Path(v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,11 +126,11 @@ impl<T> crate::PayloadExtractor for Query<T> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "validify")]
|
||||
impl<T: validify::Validify> crate::HasValidify for Query<T> {
|
||||
impl<T: validify::Validify + validify::ValidifyPayload> crate::HasValidify for Query<T> {
|
||||
type Validify = T;
|
||||
type PayloadExtractor = Query<T::Payload>;
|
||||
|
||||
fn from_validified(v: Self::Validify) -> Self {
|
||||
fn from_validify(v: Self::Validify) -> Self {
|
||||
Query(v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,10 +126,10 @@ impl<T> crate::PayloadExtractor for Toml<T> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "validify")]
|
||||
impl<T: validify::Validify> crate::HasValidify for Toml<T> {
|
||||
impl<T: validify::Validify + validify::ValidifyPayload> crate::HasValidify for Toml<T> {
|
||||
type Validify = T;
|
||||
type PayloadExtractor = Toml<T::Payload>;
|
||||
fn from_validified(v: Self::Validify) -> Self {
|
||||
fn from_validify(v: Self::Validify) -> Self {
|
||||
Toml(v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 = <Self::Validify as Validify>::Payload>;
|
||||
type PayloadExtractor: PayloadExtractor<Payload = <Self::Validify as ValidifyPayload>::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<State, Extractor> FromRequest<State> for Validified<Extractor>
|
||||
where
|
||||
State: Send + Sync,
|
||||
Extractor: HasValidify,
|
||||
Extractor::Validify: Validify,
|
||||
Extractor::PayloadExtractor: FromRequest<State>,
|
||||
{
|
||||
type Rejection =
|
||||
@@ -323,10 +322,10 @@ where
|
||||
async fn from_request(req: Request, state: &State) -> Result<Self, Self::Rejection> {
|
||||
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<State, Extractor> FromRequestParts<State> for Validified<Extractor>
|
||||
where
|
||||
State: Send + Sync,
|
||||
Extractor: HasValidify,
|
||||
Extractor::Validify: Validify,
|
||||
Extractor::PayloadExtractor: FromRequestParts<State>,
|
||||
{
|
||||
type Rejection =
|
||||
@@ -344,10 +342,10 @@ where
|
||||
async fn from_request_parts(parts: &mut Parts, state: &State) -> Result<Self, Self::Rejection> {
|
||||
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)]
|
||||
|
||||
@@ -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<ParametersValidify> = Lazy::new(|| ParametersVal
|
||||
v1: String::from("ABCDEFGHIJKLMN"),
|
||||
});
|
||||
|
||||
static VALID_PARAMETERS_WITHOUT_PAYLOAD: Lazy<ParametersValidifyWithoutPayload> =
|
||||
Lazy::new(|| ParametersValidifyWithoutPayload {
|
||||
v0: 5,
|
||||
v1: String::from("ABCDEFG"),
|
||||
});
|
||||
|
||||
static INVALID_PARAMETERS_WITHOUT_PAYLOAD: Lazy<ParametersValidifyWithoutPayload> =
|
||||
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::<Protobuf<ParametersValidify>>(
|
||||
.execute::<Protobuf<ParametersValidifyWithoutPayload>>(
|
||||
Method::POST,
|
||||
extra_protobuf::route::EXTRA_PROTOBUF,
|
||||
)
|
||||
.await?;
|
||||
// Modified
|
||||
test_executor
|
||||
.execute_modified::<Protobuf<ParametersValidify>>(
|
||||
.execute_modified::<Protobuf<ParametersValidifyWithoutPayload>>(
|
||||
Method::POST,
|
||||
extra_protobuf::route::EXTRA_PROTOBUF_MODIFIED,
|
||||
)
|
||||
.await?;
|
||||
// ValidifiedByRef
|
||||
test_executor
|
||||
.execute::<Protobuf<ParametersValidify>>(
|
||||
.execute::<Protobuf<ParametersValidifyWithoutPayload>>(
|
||||
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<TypedMultipart<ParametersValidify>>,
|
||||
Validated(TypedMultipart(parameters)): Validated<
|
||||
TypedMultipart<ParametersValidifyWithoutPayload>,
|
||||
>,
|
||||
) -> StatusCode {
|
||||
check_validated(¶meters)
|
||||
}
|
||||
|
||||
pub(super) async fn extract_typed_multipart_modified(
|
||||
Modified(TypedMultipart(parameters)): Modified<TypedMultipart<ParametersValidify>>,
|
||||
Modified(TypedMultipart(parameters)): Modified<
|
||||
TypedMultipart<ParametersValidifyWithoutPayload>,
|
||||
>,
|
||||
) -> StatusCode {
|
||||
check_modified(¶meters)
|
||||
}
|
||||
|
||||
pub(super) async fn extract_typed_multipart_validified_by_ref(
|
||||
ValidifiedByRef(TypedMultipart(parameters)): ValidifiedByRef<
|
||||
TypedMultipart<ParametersValidify>,
|
||||
TypedMultipart<ParametersValidifyWithoutPayload>,
|
||||
>,
|
||||
) -> StatusCode {
|
||||
check_validified(¶meters)
|
||||
@@ -1401,7 +1443,7 @@ mod typed_multipart {
|
||||
|
||||
pub(super) async fn extract_base_multipart(
|
||||
Validated(BaseMultipart { data, .. }): Validated<
|
||||
BaseMultipart<ParametersValidify, TypedMultipartError>,
|
||||
BaseMultipart<ParametersValidifyWithoutPayload, TypedMultipartError>,
|
||||
>,
|
||||
) -> StatusCode {
|
||||
check_validated(&data)
|
||||
@@ -1409,7 +1451,7 @@ mod typed_multipart {
|
||||
|
||||
pub(super) async fn extract_base_multipart_modified(
|
||||
Modified(BaseMultipart { data, .. }): Modified<
|
||||
BaseMultipart<ParametersValidify, TypedMultipartError>,
|
||||
BaseMultipart<ParametersValidifyWithoutPayload, TypedMultipartError>,
|
||||
>,
|
||||
) -> 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<ParametersValidify, TypedMultipartError>,
|
||||
BaseMultipart<ParametersValidifyWithoutPayload, TypedMultipartError>,
|
||||
>,
|
||||
) -> 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<Protobuf<ParametersValidify>>,
|
||||
Validated(Protobuf(parameters)): Validated<Protobuf<ParametersValidifyWithoutPayload>>,
|
||||
) -> StatusCode {
|
||||
check_validated(¶meters)
|
||||
}
|
||||
|
||||
pub async fn extract_extra_protobuf_modified(
|
||||
Modified(Protobuf(parameters)): Modified<Protobuf<ParametersValidify>>,
|
||||
Modified(Protobuf(parameters)): Modified<Protobuf<ParametersValidifyWithoutPayload>>,
|
||||
) -> StatusCode {
|
||||
check_modified(¶meters)
|
||||
}
|
||||
|
||||
pub async fn extract_extra_protobuf_validified_by_ref(
|
||||
ValidifiedByRef(Protobuf(parameters)): ValidifiedByRef<Protobuf<ParametersValidify>>,
|
||||
ValidifiedByRef(Protobuf(parameters)): ValidifiedByRef<
|
||||
Protobuf<ParametersValidifyWithoutPayload>,
|
||||
>,
|
||||
) -> StatusCode {
|
||||
check_validified(¶meters)
|
||||
}
|
||||
|
||||
@@ -126,10 +126,10 @@ impl<T> crate::PayloadExtractor for Xml<T> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "validify")]
|
||||
impl<T: validify::Validify> crate::HasValidify for Xml<T> {
|
||||
impl<T: validify::Validify + validify::ValidifyPayload> crate::HasValidify for Xml<T> {
|
||||
type Validify = T;
|
||||
type PayloadExtractor = Xml<T::Payload>;
|
||||
fn from_validified(v: Self::Validify) -> Self {
|
||||
fn from_validify(v: Self::Validify) -> Self {
|
||||
Xml(v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,10 +126,10 @@ impl<T> crate::PayloadExtractor for Yaml<T> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "validify")]
|
||||
impl<T: validify::Validify> crate::HasValidify for Yaml<T> {
|
||||
impl<T: validify::Validify + validify::ValidifyPayload> crate::HasValidify for Yaml<T> {
|
||||
type Validify = T;
|
||||
type PayloadExtractor = Yaml<T::Payload>;
|
||||
fn from_validified(v: Self::Validify) -> Self {
|
||||
fn from_validify(v: Self::Validify) -> Self {
|
||||
Yaml(v)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user