add examples and support for typed_path
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
[package]
|
||||
name = "axum-valid"
|
||||
version = "0.6.0"
|
||||
version = "0.7.0"
|
||||
description = "Provide validator extractor for your axum application."
|
||||
authors = ["GengTeng <me@gteng.org>"]
|
||||
license = "MIT"
|
||||
homepage = "https://github.com/gengteng/axum-valid"
|
||||
repository = "https://github.com/gengteng/axum-valid"
|
||||
documentation = "https://docs.rs/axum-valid"
|
||||
keywords = [
|
||||
"axum",
|
||||
"validator",
|
||||
@@ -19,6 +20,9 @@ categories = [
|
||||
]
|
||||
edition = "2021"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["all_types"]
|
||||
|
||||
[dependencies]
|
||||
axum = { version = "0.6.18", default-features = false }
|
||||
validator = "0.16.0"
|
||||
@@ -70,9 +74,10 @@ yaml = ["axum-yaml"]
|
||||
into_json = ["json"]
|
||||
422 = []
|
||||
extra = ["axum-extra"]
|
||||
extra_typed_path = ["axum-extra/typed-routing"]
|
||||
extra_query = ["axum-extra/query"]
|
||||
extra_form = ["axum-extra/form"]
|
||||
extra_protobuf = ["axum-extra/protobuf"]
|
||||
all_extra_types = ["extra", "extra_query", "extra_form", "extra_protobuf"]
|
||||
all_extra_types = ["extra", "extra_typed_path", "extra_query", "extra_form", "extra_protobuf"]
|
||||
all_types = ["json", "form", "query", "typed_header", "typed_multipart", "msgpack", "yaml", "all_extra_types"]
|
||||
full = ["all_types", "422", "into_json"]
|
||||
|
||||
66
README.md
66
README.md
@@ -10,13 +10,13 @@ This crate provides a `Valid` type that can be used in combination with `Json`,
|
||||
|
||||
Additional extractors like `TypedHeader`, `MsgPack`, `Yaml` etc. are supported through optional features. The full list of supported extractors is in the Features section below.
|
||||
|
||||
## Usage
|
||||
## Basic usage
|
||||
|
||||
```shell
|
||||
cargo add axum-valid
|
||||
```
|
||||
|
||||
```rust
|
||||
```rust,no_run
|
||||
use validator::Validate;
|
||||
use serde::Deserialize;
|
||||
use axum_valid::Valid;
|
||||
@@ -31,44 +31,58 @@ pub struct Pager {
|
||||
pub page_no: usize,
|
||||
}
|
||||
|
||||
pub async fn get_page_by_query(
|
||||
pub async fn pager_from_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(
|
||||
pub async fn pager_from_json(
|
||||
Valid(Json(pager)): Valid<Json<Pager>>,
|
||||
) {
|
||||
assert!((1..=50).contains(&pager.page_size));
|
||||
assert!((1..).contains(&pager.page_no));
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let router = Router::new()
|
||||
.route("/query", get(pager_from_query))
|
||||
.route("/json", post(pager_from_json));
|
||||
axum::Server::bind(&([0u8, 0, 0, 0], 8080).into())
|
||||
.serve(router.into_make_service())
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
When validation errors occur, the extractor will automatically return 400 with validation errors as the HTTP message body.
|
||||
|
||||
To see how each extractor can be used with `Valid`, please refer to the example in the [documentation](#modules) of the corresponding module.
|
||||
|
||||
## Features
|
||||
|
||||
| Feature | Description | Default | Tests |
|
||||
|-----------------|------------------------------------------------------------------------------------------------------|---------|-------|
|
||||
| default | Enables support for `Path`, `Query`, `Json` and `Form` | ✅ | ✅ |
|
||||
| json | Enables support for `Json` | ✅ | ✅ |
|
||||
| query | Enables support for `Query` | ✅ | ✅ |
|
||||
| form | Enables support for `Form` | ✅ | ✅ |
|
||||
| typed_header | Enables support for `TypedHeader` | ❌ | ✅ |
|
||||
| typed_multipart | Enables support for `TypedMultipart` and `BaseMultipart` from `axum_typed_multipart` | ❌ | ✅ |
|
||||
| msgpack | Enables support for `MsgPack` and `MsgPackRaw` from `axum-msgpack` | ❌ | ✅ |
|
||||
| yaml | Enables support for `Yaml` from `axum-yaml` | ❌ | ✅ |
|
||||
| extra | Enables support for `Cached`, `WithRejection` from `axum-extra` | ❌ | ✅ |
|
||||
| extra_query | Enables support for `Query` from `axum-extra` | ❌ | ✅ |
|
||||
| extra_form | Enables support for `Form` from `axum-extra` | ❌ | ✅ |
|
||||
| extra_protobuf | Enables support for `Protobuf` from `axum-extra` | ❌ | ✅ |
|
||||
| all_extra_types | Enables support for all extractors above from `axum-extra` | ❌ | ✅ |
|
||||
| all_types | Enables support for all extractors above | ❌ | ✅ |
|
||||
| 422 | Use `422 Unprocessable Entity` instead of `400 Bad Request` as the status code when validation fails | ❌ | ✅ |
|
||||
| into_json | Validation errors will be serialized into JSON format and returned as the HTTP body | ❌ | ✅ |
|
||||
| full | Enables all features | ❌ | ✅ |
|
||||
| Feature | Description | Default | Example | Tests |
|
||||
|------------------|------------------------------------------------------------------------------------------------------|---------|---------|-------|
|
||||
| default | Enables support for `Path`, `Query`, `Json` and `Form` | ✅ | ✅ | ✅ |
|
||||
| json | Enables support for `Json` | ✅ | ✅ | ✅ |
|
||||
| query | Enables support for `Query` | ✅ | ✅ | ✅ |
|
||||
| form | Enables support for `Form` | ✅ | ✅ | ✅ |
|
||||
| typed_header | Enables support for `TypedHeader` | ❌ | ✅ | ✅ |
|
||||
| typed_multipart | Enables support for `TypedMultipart` and `BaseMultipart` from `axum_typed_multipart` | ❌ | ✅ | ✅ |
|
||||
| msgpack | Enables support for `MsgPack` and `MsgPackRaw` from `axum-msgpack` | ❌ | ✅ | ✅ |
|
||||
| yaml | Enables support for `Yaml` from `axum-yaml` | ❌ | ✅ | ✅ |
|
||||
| extra | Enables support for `Cached`, `WithRejection` from `axum-extra` | ❌ | ✅ | ✅ |
|
||||
| extra_typed_path | Enables support for `T: TypedPath` from `axum-extra` | ❌ | ✅ | ✅ |
|
||||
| extra_query | Enables support for `Query` from `axum-extra` | ❌ | ✅ | ✅ |
|
||||
| extra_form | Enables support for `Form` from `axum-extra` | ❌ | ✅ | ✅ |
|
||||
| extra_protobuf | Enables support for `Protobuf` from `axum-extra` | ❌ | ✅ | ✅ |
|
||||
| all_extra_types | Enables support for all extractors above from `axum-extra` | ❌ | ✅ | ✅ |
|
||||
| all_types | Enables support for all extractors above | ❌ | ✅ | ✅ |
|
||||
| 422 | Use `422 Unprocessable Entity` instead of `400 Bad Request` as the status code when validation fails | ❌ | ✅ | ✅ |
|
||||
| into_json | Validation errors will be serialized into JSON format and returned as the HTTP body | ❌ | ✅ | ✅ |
|
||||
| full | Enables all features | ❌ | ✅ | ✅ |
|
||||
|
||||
## License
|
||||
|
||||
@@ -78,4 +92,8 @@ This project is licensed under the MIT License.
|
||||
|
||||
* [axum](https://crates.io/crates/axum)
|
||||
* [validator](https://crates.io/crates/validator)
|
||||
* [serde](https://crates.io/crates/serde)
|
||||
* [serde](https://crates.io/crates/serde)
|
||||
* [axum-extra](https://crates.io/crates/axum-extra)
|
||||
* [axum-yaml](https://crates.io/crates/axum-yaml)
|
||||
* [axum-msgpack](https://crates.io/crates/axum-msgpack)
|
||||
* [axum_typed_multipart](https://crates.io/crates/axum_typed_multipart)
|
||||
219
src/extra.rs
219
src/extra.rs
@@ -1,5 +1,220 @@
|
||||
//! # Implementation of the `HasValidate` trait for the extractor in `axum-extra`.
|
||||
//! # Support for `Cached<T>` and `WithRejection<T, R>`
|
||||
//!
|
||||
//! ## Feature
|
||||
//!
|
||||
//! Enable the `extra` feature to use `Valid<Cached<T>>`, `Valid<WithRejection<T, R>>` and `WithRejection<Valid<T>, R>`.
|
||||
//!
|
||||
//! ## `Valid<Cached<T>>`
|
||||
//!
|
||||
//! ### Usage
|
||||
//!
|
||||
//! 0. Implement your own extractor `T`.
|
||||
//! 1. Implement `Clone` and `Validate` for your extractor type `T`.
|
||||
//! 2. In your handler function, use `Valid<Cached<T>>` as some parameter's type.
|
||||
//!
|
||||
//! ### Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use axum::extract::FromRequestParts;
|
||||
//! use axum::http::request::Parts;
|
||||
//! use axum::response::{IntoResponse, Response};
|
||||
//! use axum::routing::post;
|
||||
//! use axum::Router;
|
||||
//! use axum_extra::extract::Cached;
|
||||
//! use axum_valid::Valid;
|
||||
//! use validator::Validate;
|
||||
//! #[tokio::main]
|
||||
//! async fn main() -> anyhow::Result<()> {
|
||||
//! let router = Router::new().route("/cached", post(handler));
|
||||
//! axum::Server::bind(&([0u8, 0, 0, 0], 8080).into())
|
||||
//! .serve(router.into_make_service())
|
||||
//! .await?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! async fn handler(Valid(Cached(parameter)): Valid<Cached<Parameter>>) {
|
||||
//! assert!(parameter.validate().is_ok());
|
||||
//! }
|
||||
//! #[derive(Validate, Clone)]
|
||||
//! pub struct Parameter {
|
||||
//! #[validate(range(min = 5, max = 10))]
|
||||
//! pub v0: i32,
|
||||
//! #[validate(length(min = 1, max = 10))]
|
||||
//! pub v1: String,
|
||||
//! }
|
||||
//!
|
||||
//! pub struct ParameterRejection;
|
||||
//!
|
||||
//! impl IntoResponse for ParameterRejection {
|
||||
//! fn into_response(self) -> Response {
|
||||
//! todo!()
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! #[axum::async_trait]
|
||||
//! impl<S> FromRequestParts<S> for Parameter
|
||||
//! where
|
||||
//! S: Send + Sync,
|
||||
//! {
|
||||
//! type Rejection = ParameterRejection;
|
||||
//!
|
||||
//! async fn from_request_parts(_parts: &mut Parts, _: &S) -> Result<Self, Self::Rejection> {
|
||||
//! todo!()
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! ## `Valid<WithRejection<T, R>>`
|
||||
//!
|
||||
//! ### Usage
|
||||
//!
|
||||
//! 0. Implement your own extractor `T` and rejection type `R`.
|
||||
//! 1. Implement `Validate` for your extractor type `T`.
|
||||
//! 2. In your handler function, use `Valid<WithRejection<T, R>>` as some parameter's type.
|
||||
//!
|
||||
//! ### Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use axum::extract::FromRequestParts;
|
||||
//! use axum::http::request::Parts;
|
||||
//! use axum::http::StatusCode;
|
||||
//! use axum::response::{IntoResponse, Response};
|
||||
//! use axum::routing::post;
|
||||
//! use axum::Router;
|
||||
//! use axum_extra::extract::WithRejection;
|
||||
//! use axum_valid::Valid;
|
||||
//! use validator::Validate;
|
||||
//! #[tokio::main]
|
||||
//! async fn main() -> anyhow::Result<()> {
|
||||
//! let router = Router::new().route("/valid_with_rejection", post(handler));
|
||||
//! axum::Server::bind(&([0u8, 0, 0, 0], 8080).into())
|
||||
//! .serve(router.into_make_service())
|
||||
//! .await?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! async fn handler(
|
||||
//! Valid(WithRejection(parameter, _)): Valid<
|
||||
//! WithRejection<Parameter, ValidWithRejectionRejection>,
|
||||
//! >,
|
||||
//! ) {
|
||||
//! assert!(parameter.validate().is_ok());
|
||||
//! }
|
||||
//!
|
||||
//! #[derive(Validate)]
|
||||
//! pub struct Parameter {
|
||||
//! #[validate(range(min = 5, max = 10))]
|
||||
//! pub v0: i32,
|
||||
//! #[validate(length(min = 1, max = 10))]
|
||||
//! pub v1: String,
|
||||
//! }
|
||||
//!
|
||||
//! pub struct ValidWithRejectionRejection;
|
||||
//!
|
||||
//! impl IntoResponse for ValidWithRejectionRejection {
|
||||
//! fn into_response(self) -> Response {
|
||||
//! StatusCode::BAD_REQUEST.into_response()
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! #[axum::async_trait]
|
||||
//! impl<S> FromRequestParts<S> for Parameter
|
||||
//! where
|
||||
//! S: Send + Sync,
|
||||
//! {
|
||||
//! type Rejection = ValidWithRejectionRejection;
|
||||
//!
|
||||
//! async fn from_request_parts(_parts: &mut Parts, _: &S) -> Result<Self, Self::Rejection> {
|
||||
//! todo!()
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! ## `WithRejection<Valid<T>, R>`
|
||||
//!
|
||||
//! ### Usage
|
||||
//!
|
||||
//! 0. Implement your own extractor `T` and rejection type `R`.
|
||||
//! 1. Implement `Validate` and `HasValidate` for your extractor type `T`.
|
||||
//! 2. Implement `From<ValidRejection<T::Rejection>>` for `R`.
|
||||
//! 3. In your handler function, use `WithRejection<Valid<T>, R>` as some parameter's type.
|
||||
//!
|
||||
//! ### Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use axum::extract::FromRequestParts;
|
||||
//! use axum::http::request::Parts;
|
||||
//! use axum::response::{IntoResponse, Response};
|
||||
//! use axum::routing::post;
|
||||
//! use axum::Router;
|
||||
//! use axum_extra::extract::WithRejection;
|
||||
//! use axum_valid::{HasValidate, Valid, ValidRejection};
|
||||
//! use validator::Validate;
|
||||
//! #[tokio::main]
|
||||
//! async fn main() -> anyhow::Result<()> {
|
||||
//! let router = Router::new().route("/with_rejection_valid", post(handler));
|
||||
//! axum::Server::bind(&([0u8, 0, 0, 0], 8080).into())
|
||||
//! .serve(router.into_make_service())
|
||||
//! .await?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! async fn handler(
|
||||
//! WithRejection(Valid(parameter), _): WithRejection<
|
||||
//! Valid<Parameter>,
|
||||
//! WithRejectionValidRejection,
|
||||
//! >,
|
||||
//! ) {
|
||||
//! assert!(parameter.validate().is_ok());
|
||||
//! }
|
||||
//!
|
||||
//! #[derive(Validate)]
|
||||
//! pub struct Parameter {
|
||||
//! #[validate(range(min = 5, max = 10))]
|
||||
//! pub v0: i32,
|
||||
//! #[validate(length(min = 1, max = 10))]
|
||||
//! pub v1: String,
|
||||
//! }
|
||||
//!
|
||||
//! impl HasValidate for Parameter {
|
||||
//! type Validate = Self;
|
||||
//!
|
||||
//! fn get_validate(&self) -> &Self::Validate {
|
||||
//! self
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! pub struct ParameterRejection;
|
||||
//!
|
||||
//! impl IntoResponse for ParameterRejection {
|
||||
//! fn into_response(self) -> Response {
|
||||
//! todo!()
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! #[axum::async_trait]
|
||||
//! impl<S> FromRequestParts<S> for Parameter
|
||||
//! where
|
||||
//! S: Send + Sync,
|
||||
//! {
|
||||
//! type Rejection = ParameterRejection;
|
||||
//!
|
||||
//! async fn from_request_parts(_parts: &mut Parts, _: &S) -> Result<Self, Self::Rejection> {
|
||||
//! todo!()
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! pub struct WithRejectionValidRejection;
|
||||
//!
|
||||
//! impl From<ValidRejection<ParameterRejection>> for WithRejectionValidRejection {
|
||||
//! fn from(_inner: ValidRejection<ParameterRejection>) -> Self {
|
||||
//! todo!()
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! impl IntoResponse for WithRejectionValidRejection {
|
||||
//! fn into_response(self) -> Response {
|
||||
//! todo!()
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
#[cfg(feature = "extra_form")]
|
||||
pub mod form;
|
||||
@@ -7,6 +222,8 @@ pub mod form;
|
||||
pub mod protobuf;
|
||||
#[cfg(feature = "extra_query")]
|
||||
pub mod query;
|
||||
#[cfg(feature = "extra_typed_path")]
|
||||
pub mod typed_path;
|
||||
|
||||
use crate::HasValidate;
|
||||
use axum_extra::extract::{Cached, WithRejection};
|
||||
|
||||
@@ -1,5 +1,42 @@
|
||||
//! # Implementation of the `HasValidate` trait for the `Form` extractor in `axum-extra`.
|
||||
//! # Support for `Form<T>` from `axum-extra`
|
||||
//!
|
||||
//! ## Feature
|
||||
//!
|
||||
//! Enable the `extra_form` feature to use `Valid<Form<T>>`.
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! 1. Implement `Deserialize` and `Validate` for your data type `T`.
|
||||
//! 2. In your handler function, use `Valid<Form<T>>` as some parameter's type.
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use axum::routing::post;
|
||||
//! use axum::Router;
|
||||
//! use axum_extra::extract::Form;
|
||||
//! use axum_valid::Valid;
|
||||
//! use serde::Deserialize;
|
||||
//! use validator::Validate;
|
||||
//! #[tokio::main]
|
||||
//! async fn main() -> anyhow::Result<()> {
|
||||
//! let router = Router::new().route("/extra_form", post(handler));
|
||||
//! axum::Server::bind(&([0u8, 0, 0, 0], 8080).into())
|
||||
//! .serve(router.into_make_service())
|
||||
//! .await?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! async fn handler(Valid(Form(parameter)): Valid<Form<Parameter>>) {
|
||||
//! assert!(parameter.validate().is_ok());
|
||||
//! }
|
||||
//! #[derive(Validate, Deserialize)]
|
||||
//! pub struct Parameter {
|
||||
//! #[validate(range(min = 5, max = 10))]
|
||||
//! pub v0: i32,
|
||||
//! #[validate(length(min = 1, max = 10))]
|
||||
//! pub v1: String,
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use crate::HasValidate;
|
||||
use axum_extra::extract::Form;
|
||||
|
||||
@@ -1,5 +1,44 @@
|
||||
//! # Implementation of the `HasValidate` trait for the `Form` extractor.
|
||||
//! # Support for `Protobuf<T>` from `axum-extra`
|
||||
//!
|
||||
//! ## Feature
|
||||
//!
|
||||
//! Enable the `extra_protobuf` feature to use `Valid<Protobuf<T>>`.
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! 1. Implement `prost::Message` and `Validate` for your data type `T`.
|
||||
//! 2. In your handler function, use `Valid<Protobuf<T>>` as some parameter's type.
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use axum::routing::post;
|
||||
//! use axum::Router;
|
||||
//! use axum_extra::protobuf::Protobuf;
|
||||
//! use axum_valid::Valid;
|
||||
//! use validator::Validate;
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
//! async fn main() -> anyhow::Result<()> {
|
||||
//! let router = Router::new().route("/protobuf", post(handler));
|
||||
//! axum::Server::bind(&([0u8, 0, 0, 0], 8080).into())
|
||||
//! .serve(router.into_make_service())
|
||||
//! .await?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! async fn handler(Valid(Protobuf(parameter)): Valid<Protobuf<Parameter>>) {
|
||||
//! assert!(parameter.validate().is_ok());
|
||||
//! }
|
||||
//! #[derive(Validate, prost::Message)]
|
||||
//! pub struct Parameter {
|
||||
//! #[validate(range(min = 5, max = 10))]
|
||||
//! #[prost(int32, tag = "1")]
|
||||
//! pub v0: i32,
|
||||
//! #[validate(length(min = 1, max = 10))]
|
||||
//! #[prost(string, tag = "2")]
|
||||
//! pub v1: String,
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use crate::HasValidate;
|
||||
use axum_extra::protobuf::Protobuf;
|
||||
|
||||
@@ -1,5 +1,45 @@
|
||||
//! # Implementation of the `HasValidate` trait for the `Query` extractor in `axum-extra`.
|
||||
//! # Support for `Query<T>` from `axum-extra`
|
||||
//!
|
||||
//! ## Feature
|
||||
//!
|
||||
//! Enable the `extra_query` feature to use `Valid<Query<T>>`.
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! 1. Implement `Deserialize` and `Validate` for your data type `T`.
|
||||
//! 2. In your handler function, use `Valid<Query<T>>` as some parameter's type.
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use axum::routing::post;
|
||||
//! use axum::Router;
|
||||
//! use axum_extra::extract::Query;
|
||||
//! use axum_valid::Valid;
|
||||
//! use serde::Deserialize;
|
||||
//! use validator::Validate;
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
//! async fn main() -> anyhow::Result<()> {
|
||||
//! let router = Router::new().route("/extra_query", post(handler));
|
||||
//! axum::Server::bind(&([0u8, 0, 0, 0], 8080).into())
|
||||
//! .serve(router.into_make_service())
|
||||
//! .await?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//!
|
||||
//! async fn handler(Valid(Query(parameter)): Valid<Query<Parameter>>) {
|
||||
//! assert!(parameter.validate().is_ok());
|
||||
//! }
|
||||
//!
|
||||
//! #[derive(Validate, Deserialize)]
|
||||
//! pub struct Parameter {
|
||||
//! #[validate(range(min = 5, max = 10))]
|
||||
//! pub v0: i32,
|
||||
//! #[validate(length(min = 1, max = 10))]
|
||||
//! pub v1: String,
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use crate::HasValidate;
|
||||
use axum_extra::extract::Query;
|
||||
|
||||
64
src/extra/typed_path.rs
Normal file
64
src/extra/typed_path.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
//! # Support for `T: TypedPath` from `axum-extra`
|
||||
//!
|
||||
//! ## Feature
|
||||
//!
|
||||
//! Enable the `extra_typed_path` feature to use `Valid<T: TypedPath>`.
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! 1. Implement `TypedPath`, `Deserialize`, `Validate` and `HasValidate` for your data type `T`.
|
||||
//! 2. In your handler function, use `Valid<T>` as some parameter's type.
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use axum::Router;
|
||||
//! use axum_extra::routing::{RouterExt, TypedPath};
|
||||
//! use axum_valid::{HasValidate, Valid};
|
||||
//! use serde::Deserialize;
|
||||
//! use validator::Validate;
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
//! async fn main() -> anyhow::Result<()> {
|
||||
//! let router = Router::new().typed_get(handler);
|
||||
//! axum::Server::bind(&([0u8, 0, 0, 0], 8080).into())
|
||||
//! .serve(router.into_make_service())
|
||||
//! .await?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//!
|
||||
//! async fn handler(parameter: Valid<Parameter>) {
|
||||
//! assert!(parameter.validate().is_ok());
|
||||
//! }
|
||||
//!
|
||||
//! #[derive(TypedPath, Deserialize, Validate)]
|
||||
//! #[typed_path("/extra_typed_path/:v0/:v1")]
|
||||
//! struct Parameter {
|
||||
//! #[validate(range(min = 5, max = 10))]
|
||||
//! v0: i32,
|
||||
//! #[validate(length(min = 1, max = 10))]
|
||||
//! v1: String,
|
||||
//! }
|
||||
//!
|
||||
//! impl HasValidate for Parameter {
|
||||
//! type Validate = Self;
|
||||
//!
|
||||
//! fn get_validate(&self) -> &Self::Validate {
|
||||
//! self
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use crate::Valid;
|
||||
use axum_extra::routing::TypedPath;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
impl<T: Display> Display for Valid<T> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: TypedPath + Display> TypedPath for Valid<T> {
|
||||
const PATH: &'static str = T::PATH;
|
||||
}
|
||||
39
src/form.rs
39
src/form.rs
@@ -1,5 +1,42 @@
|
||||
//! # Implementation of the `HasValidate` trait for the `Form` extractor.
|
||||
//! # Support for `Form<T>`
|
||||
//!
|
||||
//! ## Feature
|
||||
//!
|
||||
//! Enable the `form` feature (enabled by default) to use `Valid<Form<T>>`.
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! 1. Implement `Deserialize` and `Validate` for your data type `T`.
|
||||
//! 2. In your handler function, use `Valid<Form<T>>` as some parameter's type.
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use axum::routing::post;
|
||||
//! use axum::Form;
|
||||
//! use axum::Router;
|
||||
//! use axum_valid::Valid;
|
||||
//! use serde::Deserialize;
|
||||
//! use validator::Validate;
|
||||
//! #[tokio::main]
|
||||
//! async fn main() -> anyhow::Result<()> {
|
||||
//! let router = Router::new().route("/form", post(handler));
|
||||
//! axum::Server::bind(&([0u8, 0, 0, 0], 8080).into())
|
||||
//! .serve(router.into_make_service())
|
||||
//! .await?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! async fn handler(Valid(Form(parameter)): Valid<Form<Parameter>>) {
|
||||
//! assert!(parameter.validate().is_ok());
|
||||
//! }
|
||||
//! #[derive(Validate, Deserialize)]
|
||||
//! pub struct Parameter {
|
||||
//! #[validate(range(min = 5, max = 10))]
|
||||
//! pub v0: i32,
|
||||
//! #[validate(length(min = 1, max = 10))]
|
||||
//! pub v1: String,
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use crate::HasValidate;
|
||||
use axum::Form;
|
||||
|
||||
39
src/json.rs
39
src/json.rs
@@ -1,5 +1,42 @@
|
||||
//! # Implementation of the `HasValidate` trait for the `Json` extractor.
|
||||
//! # Support for `Json<T>`
|
||||
//!
|
||||
//! ## Feature
|
||||
//!
|
||||
//! Enable the `json` feature (enabled by default) to use `Valid<Json<T>>`.
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! 1. Implement `Deserialize` and `Validate` for your data type `T`.
|
||||
//! 2. In your handler function, use `Valid<Json<T>>` as some parameter's type.
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use axum::routing::post;
|
||||
//! use axum::Json;
|
||||
//! use axum::Router;
|
||||
//! use axum_valid::Valid;
|
||||
//! use serde::Deserialize;
|
||||
//! use validator::Validate;
|
||||
//! #[tokio::main]
|
||||
//! async fn main() -> anyhow::Result<()> {
|
||||
//! let router = Router::new().route("/json", post(handler));
|
||||
//! axum::Server::bind(&([0u8, 0, 0, 0], 8080).into())
|
||||
//! .serve(router.into_make_service())
|
||||
//! .await?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! async fn handler(Valid(Json(parameter)): Valid<Json<Parameter>>) {
|
||||
//! assert!(parameter.validate().is_ok());
|
||||
//! }
|
||||
//! #[derive(Validate, Deserialize)]
|
||||
//! pub struct Parameter {
|
||||
//! #[validate(range(min = 5, max = 10))]
|
||||
//! pub v0: i32,
|
||||
//! #[validate(length(min = 1, max = 10))]
|
||||
//! pub v1: String,
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use crate::HasValidate;
|
||||
use axum::Json;
|
||||
|
||||
@@ -116,6 +116,9 @@ impl<E: IntoResponse> IntoResponse for ValidRejection<E> {
|
||||
}
|
||||
|
||||
/// Trait for types that can provide a reference that can be validated for correctness.
|
||||
///
|
||||
/// Extractor types `T` that implement this trait can be used with `Valid`.
|
||||
///
|
||||
pub trait HasValidate {
|
||||
/// Inner type that can be validated for correctness
|
||||
type Validate: Validate;
|
||||
|
||||
@@ -1,5 +1,51 @@
|
||||
//! # Implementation of the `HasValidate` trait for the `MsgPack` extractor.
|
||||
//! # Support for `MsgPack<T>` and `MsgPackRaw<T>` from `axum-msgpack`
|
||||
//!
|
||||
//! ## Feature
|
||||
//!
|
||||
//! Enable the `msgpack` feature to use `Valid<MsgPack<T>>` and `Valid<MsgPackRaw<T>>`.
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! 1. Implement `Deserialize` and `Validate` for your data type `T`.
|
||||
//! 2. In your handler function, use `Valid<MsgPack<T>>` or `Valid<MsgPackRaw<T>>` as some parameter's type.
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use axum::routing::post;
|
||||
//! use axum::Router;
|
||||
//! use axum_msgpack::{MsgPack, MsgPackRaw};
|
||||
//! use axum_valid::Valid;
|
||||
//! use serde::Deserialize;
|
||||
//! use validator::Validate;
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
//! async fn main() -> anyhow::Result<()> {
|
||||
//! let router = Router::new()
|
||||
//! .route("/msgpack", post(handler))
|
||||
//! .route("/msgpackraw", post(raw_handler));
|
||||
//! axum::Server::bind(&([0u8, 0, 0, 0], 8080).into())
|
||||
//! .serve(router.into_make_service())
|
||||
//! .await?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//!
|
||||
//! async fn handler(Valid(MsgPack(parameter)): Valid<MsgPack<Parameter>>) {
|
||||
//! assert!(parameter.validate().is_ok());
|
||||
//! }
|
||||
//!
|
||||
//! async fn raw_handler(Valid(MsgPackRaw(parameter)): Valid<MsgPackRaw<Parameter>>) {
|
||||
//! assert!(parameter.validate().is_ok());
|
||||
//! }
|
||||
//!
|
||||
//! #[derive(Validate, Deserialize)]
|
||||
//! pub struct Parameter {
|
||||
//! #[validate(range(min = 5, max = 10))]
|
||||
//! pub v0: i32,
|
||||
//! #[validate(length(min = 1, max = 10))]
|
||||
//! pub v1: String,
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use crate::HasValidate;
|
||||
use axum_msgpack::{MsgPack, MsgPackRaw};
|
||||
|
||||
38
src/path.rs
38
src/path.rs
@@ -1,5 +1,41 @@
|
||||
//! # Implementation of the `HasValidate` trait for the `Path` extractor.
|
||||
//! # Support for `Path<T>`
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! 1. Implement `Deserialize` and `Validate` for your data type `T`.
|
||||
//! 2. In your handler function, use `Valid<Path<T>>` as some parameter's type.
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use axum::extract::Path;
|
||||
//! use axum::routing::post;
|
||||
//! use axum::Router;
|
||||
//! use axum_valid::Valid;
|
||||
//! use serde::Deserialize;
|
||||
//! use validator::Validate;
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
//! async fn main() -> anyhow::Result<()> {
|
||||
//! let router = Router::new().route("/path/:v0/:v1", post(handler));
|
||||
//! axum::Server::bind(&([0u8, 0, 0, 0], 8080).into())
|
||||
//! .serve(router.into_make_service())
|
||||
//! .await?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//!
|
||||
//! async fn handler(Valid(Path(parameter)): Valid<Path<Parameter>>) {
|
||||
//! assert!(parameter.validate().is_ok());
|
||||
//! }
|
||||
//!
|
||||
//! #[derive(Validate, Deserialize)]
|
||||
//! pub struct Parameter {
|
||||
//! #[validate(range(min = 5, max = 10))]
|
||||
//! pub v0: i32,
|
||||
//! #[validate(length(min = 1, max = 10))]
|
||||
//! pub v1: String,
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use crate::HasValidate;
|
||||
use axum::extract::Path;
|
||||
|
||||
42
src/query.rs
42
src/query.rs
@@ -1,5 +1,45 @@
|
||||
//! # Implementation of the `HasValidate` trait for the `Query` extractor.
|
||||
//! # Support for `Query<T>`
|
||||
//!
|
||||
//! ## Feature
|
||||
//!
|
||||
//! Enable the `query` feature (enabled by default) to use `Valid<Query<T>>`.
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! 1. Implement `Deserialize` and `Validate` for your data type `T`.
|
||||
//! 2. In your handler function, use `Valid<Query<T>>` as some parameter's type.
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use axum::extract::Query;
|
||||
//! use axum::routing::post;
|
||||
//! use axum::Router;
|
||||
//! use axum_valid::Valid;
|
||||
//! use serde::Deserialize;
|
||||
//! use validator::Validate;
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
//! async fn main() -> anyhow::Result<()> {
|
||||
//! let router = Router::new().route("/query", post(handler));
|
||||
//! axum::Server::bind(&([0u8, 0, 0, 0], 8080).into())
|
||||
//! .serve(router.into_make_service())
|
||||
//! .await?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//!
|
||||
//! async fn handler(Valid(Query(parameter)): Valid<Query<Parameter>>) {
|
||||
//! assert!(parameter.validate().is_ok());
|
||||
//! }
|
||||
//!
|
||||
//! #[derive(Validate, Deserialize)]
|
||||
//! pub struct Parameter {
|
||||
//! #[validate(range(min = 5, max = 10))]
|
||||
//! pub v0: i32,
|
||||
//! #[validate(length(min = 1, max = 10))]
|
||||
//! pub v1: String,
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use crate::HasValidate;
|
||||
use axum::extract::Query;
|
||||
|
||||
98
src/test.rs
98
src/test.rs
@@ -96,6 +96,12 @@ async fn test_main() -> anyhow::Result<()> {
|
||||
post(extra::extract_with_rejection_valid),
|
||||
);
|
||||
|
||||
#[cfg(feature = "extra_typed_path")]
|
||||
let router = router.route(
|
||||
extra_typed_path::route::EXTRA_TYPED_PATH,
|
||||
get(extra_typed_path::extract_extra_typed_path),
|
||||
);
|
||||
|
||||
#[cfg(feature = "extra_query")]
|
||||
let router = router.route(
|
||||
extra_query::route::EXTRA_QUERY,
|
||||
@@ -246,6 +252,61 @@ async fn test_main() -> anyhow::Result<()> {
|
||||
.await?;
|
||||
}
|
||||
|
||||
#[cfg(feature = "extra_typed_path")]
|
||||
{
|
||||
{
|
||||
let extra_typed_path_type_name = "T: TypedPath";
|
||||
let valid_extra_typed_path_response = test_executor
|
||||
.client()
|
||||
.get(format!(
|
||||
"{}/extra_typed_path/{}/{}",
|
||||
server_url, VALID_PARAMETERS.v0, VALID_PARAMETERS.v1
|
||||
))
|
||||
.send()
|
||||
.await?;
|
||||
assert_eq!(
|
||||
valid_extra_typed_path_response.status(),
|
||||
StatusCode::OK,
|
||||
"Valid '{}' test failed.",
|
||||
extra_typed_path_type_name
|
||||
);
|
||||
|
||||
let error_extra_typed_path_response = test_executor
|
||||
.client()
|
||||
.get(format!("{}/extra_typed_path/not_i32/path", server_url))
|
||||
.send()
|
||||
.await?;
|
||||
assert_eq!(
|
||||
error_extra_typed_path_response.status(),
|
||||
StatusCode::BAD_REQUEST,
|
||||
"Error '{}' test failed.",
|
||||
extra_typed_path_type_name
|
||||
);
|
||||
|
||||
let invalid_extra_typed_path_response = test_executor
|
||||
.client()
|
||||
.get(format!(
|
||||
"{}/extra_typed_path/{}/{}",
|
||||
server_url, INVALID_PARAMETERS.v0, INVALID_PARAMETERS.v1
|
||||
))
|
||||
.send()
|
||||
.await?;
|
||||
assert_eq!(
|
||||
invalid_extra_typed_path_response.status(),
|
||||
VALIDATION_ERROR_STATUS,
|
||||
"Invalid '{}' test failed.",
|
||||
extra_typed_path_type_name
|
||||
);
|
||||
#[cfg(feature = "into_json")]
|
||||
check_json(
|
||||
extra_typed_path_type_name,
|
||||
invalid_extra_typed_path_response,
|
||||
)
|
||||
.await;
|
||||
println!("All {} tests passed.", extra_typed_path_type_name);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "extra_query")]
|
||||
{
|
||||
use axum_extra::extract::Query;
|
||||
@@ -411,7 +472,7 @@ fn validate_again<V: Validate>(validate: V) -> StatusCode {
|
||||
mod typed_header {
|
||||
|
||||
pub(crate) mod route {
|
||||
pub const TYPED_HEADER: &str = "/typedHeader";
|
||||
pub const TYPED_HEADER: &str = "/typed_header";
|
||||
}
|
||||
|
||||
use super::{validate_again, Parameters};
|
||||
@@ -665,6 +726,41 @@ mod extra {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "extra_typed_path")]
|
||||
mod extra_typed_path {
|
||||
use crate::test::validate_again;
|
||||
use crate::{HasValidate, Valid};
|
||||
use axum::http::StatusCode;
|
||||
use axum_extra::routing::TypedPath;
|
||||
use serde::Deserialize;
|
||||
use validator::Validate;
|
||||
|
||||
pub mod route {
|
||||
pub const EXTRA_TYPED_PATH: &str = "/extra_typed_path/:v0/:v1";
|
||||
}
|
||||
|
||||
#[derive(Validate, TypedPath, Deserialize)]
|
||||
#[typed_path("/extra_typed_path/:v0/:v1")]
|
||||
pub struct TypedPathParam {
|
||||
#[validate(range(min = 5, max = 10))]
|
||||
v0: i32,
|
||||
#[validate(length(min = 1, max = 10))]
|
||||
v1: String,
|
||||
}
|
||||
|
||||
impl HasValidate for TypedPathParam {
|
||||
type Validate = Self;
|
||||
|
||||
fn get_validate(&self) -> &Self::Validate {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn extract_extra_typed_path(Valid(param): Valid<TypedPathParam>) -> StatusCode {
|
||||
validate_again(param)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "extra_query")]
|
||||
mod extra_query {
|
||||
use crate::test::{validate_again, Parameters};
|
||||
|
||||
@@ -1,5 +1,65 @@
|
||||
//! # Implementation of the `HasValidate` trait for the `TypedHeader` extractor.
|
||||
//! # Support for `TypedHeader<T>`
|
||||
//!
|
||||
//! ## Feature
|
||||
//!
|
||||
//! Enable the `typed_header` feature to use `Valid<TypedHeader<T>>`.
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! 1. Implement `Header` and `Validate` for your data type `T`.
|
||||
//! 2. In your handler function, use `Valid<TypedHeader<T>>` as some parameter's type.
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use axum::headers::{Error, Header, HeaderValue};
|
||||
//! use axum::http::HeaderName;
|
||||
//! use axum::routing::post;
|
||||
//! use axum::{Router, TypedHeader};
|
||||
//! use axum_valid::Valid;
|
||||
//! use validator::Validate;
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
//! async fn main() -> anyhow::Result<()> {
|
||||
//! let router = Router::new().route("/typed_header", post(handler));
|
||||
//! axum::Server::bind(&([0u8, 0, 0, 0], 8080).into())
|
||||
//! .serve(router.into_make_service())
|
||||
//! .await?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//!
|
||||
//! async fn handler(Valid(TypedHeader(parameter)): Valid<TypedHeader<Parameter>>) {
|
||||
//! assert!(parameter.validate().is_ok());
|
||||
//! }
|
||||
//!
|
||||
//! #[derive(Validate)]
|
||||
//! pub struct Parameter {
|
||||
//! #[validate(range(min = 5, max = 10))]
|
||||
//! pub v0: i32,
|
||||
//! #[validate(length(min = 1, max = 10))]
|
||||
//! pub v1: String,
|
||||
//! }
|
||||
//!
|
||||
//! static HEADER_NAME: HeaderName = HeaderName::from_static("my-header");
|
||||
//!
|
||||
//! impl Header for Parameter {
|
||||
//! fn name() -> &'static HeaderName {
|
||||
//! &HEADER_NAME
|
||||
//! }
|
||||
//!
|
||||
//! fn decode<'i, I>(_values: &mut I) -> Result<Self, Error>
|
||||
//! where
|
||||
//! Self: Sized,
|
||||
//! I: Iterator<Item = &'i HeaderValue>,
|
||||
//! {
|
||||
//! todo!()
|
||||
//! }
|
||||
//!
|
||||
//! fn encode<E: Extend<HeaderValue>>(&self, _values: &mut E) {
|
||||
//! todo!()
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use crate::HasValidate;
|
||||
use axum::TypedHeader;
|
||||
|
||||
@@ -1,5 +1,54 @@
|
||||
//! # Implementation of the `HasValidate` trait for the `TypedMultipart` extractor.
|
||||
//! # Support for `TypedMultipart<T>` and `BaseMultipart<T, R>` from `axum_typed_multipart`
|
||||
//!
|
||||
//! ## Feature
|
||||
//!
|
||||
//! Enable the `typed_multipart` feature to use `Valid<TypedMultipart<T>>` and `Valid<BaseMultipart<T, R>>`.
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! 1. Implement `TryFromMultipart` and `Validate` for your data type `T`.
|
||||
//! 2. In your handler function, use `Valid<TypedMultipart<T>>` or `Valid<BaseMultipart<T, E>` as some parameter's type.
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use axum::routing::post;
|
||||
//! use axum::Router;
|
||||
//! use axum_typed_multipart::{BaseMultipart, TryFromMultipart, TypedMultipart, TypedMultipartError};
|
||||
//! use axum_valid::Valid;
|
||||
//! use validator::Validate;
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
//! async fn main() -> anyhow::Result<()> {
|
||||
//! let router = Router::new()
|
||||
//! .route("/typed_multipart", post(handler))
|
||||
//! .route("/base_multipart", post(base_handler));
|
||||
//! axum::Server::bind(&([0u8, 0, 0, 0], 8080).into())
|
||||
//! .serve(router.into_make_service())
|
||||
//! .await?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//!
|
||||
//! async fn handler(Valid(TypedMultipart(parameter)): Valid<TypedMultipart<Parameter>>) {
|
||||
//! assert!(parameter.validate().is_ok());
|
||||
//! }
|
||||
//!
|
||||
//! async fn base_handler(
|
||||
//! Valid(BaseMultipart {
|
||||
//! data: parameter, ..
|
||||
//! }): Valid<BaseMultipart<Parameter, TypedMultipartError>>,
|
||||
//! ) {
|
||||
//! assert!(parameter.validate().is_ok());
|
||||
//! }
|
||||
//!
|
||||
//! #[derive(TryFromMultipart, Validate)]
|
||||
//! struct Parameter {
|
||||
//! #[validate(range(min = 5, max = 10))]
|
||||
//! v0: i32,
|
||||
//! #[validate(length(min = 1, max = 10))]
|
||||
//! v1: String,
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use crate::HasValidate;
|
||||
use axum_typed_multipart::{BaseMultipart, TypedMultipart};
|
||||
|
||||
43
src/yaml.rs
43
src/yaml.rs
@@ -1,5 +1,46 @@
|
||||
//! # Implementation of the `HasValidate` trait for the `Yaml` extractor.
|
||||
//! # Support for `Yaml<T>` from `axum-yaml`
|
||||
//!
|
||||
//! ## Feature
|
||||
//!
|
||||
//! Enable the `yaml` feature to use `Valid<Yaml<T>>`.
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! 1. Implement `Deserialize` and `Validate` for your data type `T`.
|
||||
//! 2. In your handler function, use `Valid<Yaml<T>>` as some parameter's type.
|
||||
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use axum::routing::post;
|
||||
//! use axum::Router;
|
||||
//! use axum_valid::Valid;
|
||||
//! use axum_yaml::Yaml;
|
||||
//! use serde::Deserialize;
|
||||
//! use validator::Validate;
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
//! async fn main() -> anyhow::Result<()> {
|
||||
//! let router = Router::new().route("/yaml", post(handler));
|
||||
//! axum::Server::bind(&([0u8, 0, 0, 0], 8080).into())
|
||||
//! .serve(router.into_make_service())
|
||||
//! .await?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//!
|
||||
//! async fn handler(parameter: Valid<Yaml<Parameter>>) {
|
||||
//! assert!(parameter.validate().is_ok());
|
||||
//! }
|
||||
//!
|
||||
//! #[derive(Deserialize, Validate)]
|
||||
//! struct Parameter {
|
||||
//! #[validate(range(min = 5, max = 10))]
|
||||
//! v0: i32,
|
||||
//! #[validate(length(min = 1, max = 10))]
|
||||
//! v1: String,
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use crate::HasValidate;
|
||||
use axum_yaml::Yaml;
|
||||
|
||||
Reference in New Issue
Block a user