Refactor: Split HasValidate implementations for four different extractors into multiple files and export them using feature flags

This commit is contained in:
gengteng
2023-07-21 21:01:10 +08:00
parent 845b81d134
commit 295ae17697
8 changed files with 111 additions and 61 deletions

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "axum-valid" name = "axum-valid"
version = "0.2.2" version = "0.2.3"
description = "Validation tools for axum using the validator library." description = "Validation tools for axum using the validator library."
authors = ["GengTeng <me@gteng.org>"] authors = ["GengTeng <me@gteng.org>"]
license = "MIT" license = "MIT"
@@ -20,5 +20,16 @@ categories = [
edition = "2021" edition = "2021"
[dependencies] [dependencies]
axum = "0.6.18" axum = { version = "0.6.18", default-features = false }
validator = "0.16.0" validator = "0.16.0"
[dev-dependencies]
anyhow = "1.0.71"
tokio = { version = "1.28.2", features = ["full"] }
reqwest = { version = "0.11.18", features = ["json"] }
[features]
default = ["json", "form", "query"]
json = ["axum/json"]
form = ["axum/form"]
query = ["axum/query"]

2
examples/basic.rs Normal file
View File

@@ -0,0 +1,2 @@
#[tokio::main]
async fn main() {}

2
examples/custom.rs Normal file
View File

@@ -0,0 +1,2 @@
#[tokio::main]
async fn main() {}

21
src/form.rs Normal file
View File

@@ -0,0 +1,21 @@
//! # Implementation of the `HasValidate` trait for the `Form` extractor.
//!
use crate::{HasValidate, ValidRejection};
use axum::extract::rejection::FormRejection;
use axum::Form;
use validator::Validate;
impl<T: Validate> HasValidate for Form<T> {
type Validate = T;
type Rejection = FormRejection;
fn get_validate(&self) -> &T {
&self.0
}
}
impl From<FormRejection> for ValidRejection<FormRejection> {
fn from(value: FormRejection) -> Self {
Self::Inner(value)
}
}

21
src/json.rs Normal file
View File

@@ -0,0 +1,21 @@
//! # Implementation of the `HasValidate` trait for the `Json` extractor.
//!
use crate::{HasValidate, ValidRejection};
use axum::extract::rejection::JsonRejection;
use axum::Json;
use validator::Validate;
impl<T: Validate> HasValidate for Json<T> {
type Validate = T;
type Rejection = JsonRejection;
fn get_validate(&self) -> &T {
&self.0
}
}
impl From<JsonRejection> for ValidRejection<JsonRejection> {
fn from(value: JsonRejection) -> Self {
Self::Inner(value)
}
}

View File

@@ -1,12 +1,19 @@
#![doc = include_str!("../README.md")] #![doc = include_str!("../README.md")]
#![deny(unsafe_code, missing_docs, clippy::unwrap_used)] #![deny(unsafe_code, missing_docs, clippy::unwrap_used)]
use axum::extract::rejection::{FormRejection, JsonRejection, PathRejection, QueryRejection}; #[cfg(feature = "form")]
use axum::extract::{FromRequest, FromRequestParts, Path, Query}; pub mod form;
#[cfg(feature = "json")]
pub mod json;
pub mod path;
#[cfg(feature = "query")]
pub mod query;
use axum::async_trait;
use axum::extract::{FromRequest, FromRequestParts};
use axum::http::request::Parts; use axum::http::request::Parts;
use axum::http::{Request, StatusCode}; use axum::http::{Request, StatusCode};
use axum::response::{IntoResponse, Response}; use axum::response::{IntoResponse, Response};
use axum::{async_trait, Form, Json};
use validator::{Validate, ValidationErrors}; use validator::{Validate, ValidationErrors};
/// Valid entity extractor /// Valid entity extractor
@@ -39,30 +46,6 @@ impl<E: IntoResponse> IntoResponse for ValidRejection<E> {
} }
} }
impl From<JsonRejection> for ValidRejection<JsonRejection> {
fn from(value: JsonRejection) -> Self {
Self::Inner(value)
}
}
impl From<QueryRejection> for ValidRejection<QueryRejection> {
fn from(value: QueryRejection) -> Self {
Self::Inner(value)
}
}
impl From<PathRejection> for ValidRejection<PathRejection> {
fn from(value: PathRejection) -> Self {
Self::Inner(value)
}
}
impl From<FormRejection> for ValidRejection<FormRejection> {
fn from(value: FormRejection) -> Self {
Self::Inner(value)
}
}
/// Trait for types that can provide a reference that can be validated for correctness. /// 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 /// Inner type that can be validated for correctness
@@ -74,38 +57,6 @@ pub trait HasValidate {
fn get_validate(&self) -> &Self::Validate; fn get_validate(&self) -> &Self::Validate;
} }
impl<T: Validate> HasValidate for Json<T> {
type Validate = T;
type Rejection = JsonRejection;
fn get_validate(&self) -> &T {
&self.0
}
}
impl<T: Validate> HasValidate for Form<T> {
type Validate = T;
type Rejection = FormRejection;
fn get_validate(&self) -> &T {
&self.0
}
}
impl<T: Validate> HasValidate for Query<T> {
type Validate = T;
type Rejection = QueryRejection;
fn get_validate(&self) -> &T {
&self.0
}
}
impl<T: Validate> HasValidate for Path<T> {
type Validate = T;
type Rejection = PathRejection;
fn get_validate(&self) -> &T {
&self.0
}
}
#[async_trait] #[async_trait]
impl<S, B, T> FromRequest<S, B> for Valid<T> impl<S, B, T> FromRequest<S, B> for Valid<T>
where where

21
src/path.rs Normal file
View File

@@ -0,0 +1,21 @@
//! # Implementation of the `HasValidate` trait for the `Path` extractor.
//!
use crate::{HasValidate, ValidRejection};
use axum::extract::rejection::PathRejection;
use axum::extract::Path;
use validator::Validate;
impl<T: Validate> HasValidate for Path<T> {
type Validate = T;
type Rejection = PathRejection;
fn get_validate(&self) -> &T {
&self.0
}
}
impl From<PathRejection> for ValidRejection<PathRejection> {
fn from(value: PathRejection) -> Self {
Self::Inner(value)
}
}

21
src/query.rs Normal file
View File

@@ -0,0 +1,21 @@
//! # Implementation of the `HasValidate` trait for the `Query` extractor.
//!
use crate::{HasValidate, ValidRejection};
use axum::extract::rejection::QueryRejection;
use axum::extract::Query;
use validator::Validate;
impl<T: Validate> HasValidate for Query<T> {
type Validate = T;
type Rejection = QueryRejection;
fn get_validate(&self) -> &T {
&self.0
}
}
impl From<QueryRejection> for ValidRejection<QueryRejection> {
fn from(value: QueryRejection) -> Self {
Self::Inner(value)
}
}