This commit is contained in:
gengteng
2023-06-06 12:10:45 +08:00
parent 43611707e2
commit 0e5d7c6edb
3 changed files with 41 additions and 7 deletions

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "axum-valid" name = "axum-valid"
version = "0.1.0" version = "0.2.0"
description = "Validator for axum" description = "Validator for axum"
authors = ["GengTeng <me@gteng.org>"] authors = ["GengTeng <me@gteng.org>"]
license = "MIT" license = "MIT"
@@ -19,9 +19,6 @@ categories = [
] ]
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
axum = "0.6.18" axum = "0.6.18"
validator = "0.16.0" validator = "0.16.0"

View File

@@ -1,2 +1,33 @@
# axum-valid # axum-valid
The Valid crate provides a `Valid` type that can be used in combination with `Json`, `Path`, `Query`, and `Form` types to validate the entities that implement the `Validate` trait.
## Usage
```rust
use validator::Validate;
use serde::Deserialize;
#[derive(Debug, Validate, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Pager {
#[validate(range(min = 1, max = 50))]
page_size: usize,
#[validate(range(min = 1))]
page_no: usize,
}
pub async fn get_page_by_query(
Valid(Query(pager)): Valid<Query<Pager>>,
) {
assert!((1..=50).contains(pager.page_size));
assert!((1..).contains(pager.page_no));
}
pub async fn get_page_by_json(
Valid(Json(pager)): Valid<Json<Pager>>,
) {
assert!((1..=50).contains(pager.page_size));
assert!((1..).contains(pager.page_no));
}
```

View File

@@ -6,9 +6,12 @@ use axum::response::{IntoResponse, Response};
use axum::{async_trait, Form, Json}; use axum::{async_trait, Form, Json};
use validator::{Validate, ValidationErrors}; use validator::{Validate, ValidationErrors};
/// Valid entity extractor
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
pub struct Valid<T>(pub T); pub struct Valid<T>(pub T);
/// If the valid extractor fails it'll use this "rejection" type.
/// This rejection type can be converted into a response.
pub enum ValidRejection<E> { pub enum ValidRejection<E> {
Valid(ValidationErrors), Valid(ValidationErrors),
Inner(E), Inner(E),
@@ -55,9 +58,14 @@ impl From<FormRejection> for ValidRejection<FormRejection> {
} }
} }
/// Trait for types that can provide a reference that can be validated for correctness.
pub trait HasValidate { pub trait HasValidate {
/// Inner type that can be validated for correctness
type Validate: Validate; type Validate: Validate;
type Rejection; /// If the inner extractor fails it'll use this "rejection" type.
/// A rejection is a kind of error that can be converted into a response.
type Rejection: IntoResponse;
/// get the inner type
fn get_validate(&self) -> &Self::Validate; fn get_validate(&self) -> &Self::Validate;
} }
@@ -100,7 +108,6 @@ where
B: Send + Sync + 'static, B: Send + Sync + 'static,
T: HasValidate + FromRequest<S, B>, T: HasValidate + FromRequest<S, B>,
T::Validate: Validate, T::Validate: Validate,
<T as HasValidate>::Rejection: IntoResponse,
ValidRejection<<T as HasValidate>::Rejection>: From<<T as FromRequest<S, B>>::Rejection>, ValidRejection<<T as HasValidate>::Rejection>: From<<T as FromRequest<S, B>>::Rejection>,
{ {
type Rejection = ValidRejection<<T as HasValidate>::Rejection>; type Rejection = ValidRejection<<T as HasValidate>::Rejection>;
@@ -118,7 +125,6 @@ where
S: Send + Sync + 'static, S: Send + Sync + 'static,
T: HasValidate + FromRequestParts<S>, T: HasValidate + FromRequestParts<S>,
T::Validate: Validate, T::Validate: Validate,
<T as HasValidate>::Rejection: IntoResponse,
ValidRejection<<T as HasValidate>::Rejection>: From<<T as FromRequestParts<S>>::Rejection>, ValidRejection<<T as HasValidate>::Rejection>: From<<T as FromRequestParts<S>>::Rejection>,
{ {
type Rejection = ValidRejection<<T as HasValidate>::Rejection>; type Rejection = ValidRejection<<T as HasValidate>::Rejection>;