refactor ValidationContext
This commit is contained in:
136
src/lib.rs
136
src/lib.rs
@@ -128,9 +128,10 @@ impl<E, A> ValidEx<E, A> {
|
|||||||
/// the HTTP status code and response body returned on validation failure.
|
/// the HTTP status code and response body returned on validation failure.
|
||||||
///
|
///
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct ValidationContext {
|
pub struct ValidationContext<Arguments> {
|
||||||
/// Validation error response builder
|
/// Validation error response builder
|
||||||
response_builder: fn(ValidationErrors) -> Response,
|
response_builder: fn(ValidationErrors) -> Response,
|
||||||
|
arguments: Arguments,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "json")]
|
#[cfg(feature = "json")]
|
||||||
@@ -146,7 +147,7 @@ fn string_response_builder(ve: ValidationErrors) -> Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ValidationContext {
|
impl<Arguments: Default> Default for ValidationContext<Arguments> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
fn response_builder(ve: ValidationErrors) -> Response {
|
fn response_builder(ve: ValidationErrors) -> Response {
|
||||||
#[cfg(feature = "into_json")]
|
#[cfg(feature = "into_json")]
|
||||||
@@ -159,11 +160,14 @@ impl Default for ValidationContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Self { response_builder }
|
Self {
|
||||||
|
response_builder,
|
||||||
|
arguments: Arguments::default(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValidationContext {
|
impl ValidationContext<()> {
|
||||||
/// Construct a `ValidationContext` with a custom response builder function
|
/// Construct a `ValidationContext` with a custom response builder function
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@@ -184,7 +188,10 @@ impl ValidationContext {
|
|||||||
/// let context = ValidationContext::custom(custom_response);
|
/// let context = ValidationContext::custom(custom_response);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn custom(response_builder: fn(ValidationErrors) -> Response) -> Self {
|
pub fn custom(response_builder: fn(ValidationErrors) -> Response) -> Self {
|
||||||
Self { response_builder }
|
Self {
|
||||||
|
response_builder,
|
||||||
|
arguments: (),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a ValidationContext that returns a string response
|
/// Construct a ValidationContext that returns a string response
|
||||||
@@ -194,6 +201,7 @@ impl ValidationContext {
|
|||||||
pub fn string() -> Self {
|
pub fn string() -> Self {
|
||||||
Self {
|
Self {
|
||||||
response_builder: string_response_builder,
|
response_builder: string_response_builder,
|
||||||
|
arguments: (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,6 +215,80 @@ impl ValidationContext {
|
|||||||
pub fn json() -> Self {
|
pub fn json() -> Self {
|
||||||
Self {
|
Self {
|
||||||
response_builder: json_response_builder,
|
response_builder: json_response_builder,
|
||||||
|
arguments: (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new `ValidationContext` with arguments.
|
||||||
|
pub fn with_arguments<Arguments>(self, arguments: Arguments) -> ValidationContext<Arguments> {
|
||||||
|
ValidationContext {
|
||||||
|
response_builder: self.response_builder,
|
||||||
|
arguments,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Arguments> ValidationContext<Arguments> {
|
||||||
|
/// Construct a `ValidationContext` with a custom response builder function
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// use axum::{response::IntoResponse, Json};
|
||||||
|
/// use axum::http::StatusCode;
|
||||||
|
/// use axum::response::Response;
|
||||||
|
/// use validator::ValidationErrors;
|
||||||
|
/// use axum_valid::ValidationContext;
|
||||||
|
///
|
||||||
|
/// struct MyArguments;
|
||||||
|
///
|
||||||
|
/// fn custom_response(errors: ValidationErrors) -> Response {
|
||||||
|
/// // return response with custom status code and body
|
||||||
|
/// (StatusCode::NOT_FOUND, Json(errors)).into_response()
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let context = ValidationContext::custom_with_arguments(custom_response, MyArguments);
|
||||||
|
/// ```
|
||||||
|
pub fn custom_with_arguments(
|
||||||
|
response_builder: fn(ValidationErrors) -> Response,
|
||||||
|
arguments: Arguments,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
response_builder,
|
||||||
|
arguments,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a ValidationContext that returns a string response
|
||||||
|
///
|
||||||
|
/// This will return a response with the validation errors formatted as a string
|
||||||
|
/// The response status code will be `400 Bad Request` by default, or `422 Unprocessable Entity` if the `422` feature is enabled.
|
||||||
|
pub fn string_with_arguments(arguments: Arguments) -> Self {
|
||||||
|
Self {
|
||||||
|
response_builder: string_response_builder,
|
||||||
|
arguments,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a ValidationContext that returns a JSON response
|
||||||
|
///
|
||||||
|
/// This will return a response with the validation errors serialized as JSON.
|
||||||
|
/// The response status code will be `400 Bad Request` by default, or `422 Unprocessable Entity` if the `422` feature is enabled.
|
||||||
|
///
|
||||||
|
/// Requires the `json` feature to be enabled.
|
||||||
|
#[cfg(feature = "json")]
|
||||||
|
pub fn json_with_arguments(arguments: Arguments) -> Self {
|
||||||
|
Self {
|
||||||
|
response_builder: json_response_builder,
|
||||||
|
arguments,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new `ValidationContext` with empty arguments.
|
||||||
|
pub fn without_arguments(&self) -> ValidationContext<()> {
|
||||||
|
ValidationContext {
|
||||||
|
response_builder: self.response_builder,
|
||||||
|
arguments: (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -318,12 +400,12 @@ where
|
|||||||
B: Send + Sync + 'static,
|
B: Send + Sync + 'static,
|
||||||
E: HasValidate + FromRequest<S, B>,
|
E: HasValidate + FromRequest<S, B>,
|
||||||
E::Validate: Validate,
|
E::Validate: Validate,
|
||||||
ValidationContext: FromRef<S>,
|
ValidationContext<()>: FromRef<S>,
|
||||||
{
|
{
|
||||||
type Rejection = ValidRejection<<E as FromRequest<S, B>>::Rejection>;
|
type Rejection = ValidRejection<<E as FromRequest<S, B>>::Rejection>;
|
||||||
|
|
||||||
async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection> {
|
async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection> {
|
||||||
let context: ValidationContext = FromRef::from_ref(state);
|
let context: ValidationContext<()> = FromRef::from_ref(state);
|
||||||
let inner = E::from_request(req, state)
|
let inner = E::from_request(req, state)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ValidRejection {
|
.map_err(|e| ValidRejection {
|
||||||
@@ -347,12 +429,12 @@ where
|
|||||||
S: Send + Sync,
|
S: Send + Sync,
|
||||||
E: HasValidate + FromRequestParts<S>,
|
E: HasValidate + FromRequestParts<S>,
|
||||||
E::Validate: Validate,
|
E::Validate: Validate,
|
||||||
ValidationContext: FromRef<S>,
|
ValidationContext<()>: FromRef<S>,
|
||||||
{
|
{
|
||||||
type Rejection = ValidRejection<<E as FromRequestParts<S>>::Rejection>;
|
type Rejection = ValidRejection<<E as FromRequestParts<S>>::Rejection>;
|
||||||
|
|
||||||
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
|
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
|
||||||
let context: ValidationContext = FromRef::from_ref(state);
|
let context: ValidationContext<()> = FromRef::from_ref(state);
|
||||||
let inner = E::from_request_parts(parts, state)
|
let inner = E::from_request_parts(parts, state)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ValidRejection {
|
.map_err(|e| ValidRejection {
|
||||||
@@ -371,19 +453,22 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<S, B, E, A> FromRequest<S, B> for ValidEx<E, A>
|
impl<S, B, E, Arguments> FromRequest<S, B> for ValidEx<E, Arguments>
|
||||||
where
|
where
|
||||||
S: Send + Sync,
|
S: Send + Sync,
|
||||||
B: Send + Sync + 'static,
|
B: Send + Sync + 'static,
|
||||||
|
Arguments: Send + Sync,
|
||||||
E: for<'v> HasValidateArgs<'v> + FromRequest<S, B>,
|
E: for<'v> HasValidateArgs<'v> + FromRequest<S, B>,
|
||||||
for<'v> <E as HasValidateArgs<'v>>::ValidateArgs: ValidateArgs<'v, Args = &'v A>,
|
for<'v> <E as HasValidateArgs<'v>>::ValidateArgs: ValidateArgs<'v, Args = &'v Arguments>,
|
||||||
A: FromRef<S>,
|
ValidationContext<Arguments>: FromRef<S>,
|
||||||
ValidationContext: FromRef<S>,
|
|
||||||
{
|
{
|
||||||
type Rejection = ValidRejection<<E as FromRequest<S, B>>::Rejection>;
|
type Rejection = ValidRejection<<E as FromRequest<S, B>>::Rejection>;
|
||||||
|
|
||||||
async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection> {
|
async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection> {
|
||||||
let ValidationContext { response_builder }: ValidationContext = FromRef::from_ref(state);
|
let ValidationContext {
|
||||||
|
response_builder,
|
||||||
|
arguments,
|
||||||
|
}: ValidationContext<Arguments> = FromRef::from_ref(state);
|
||||||
let inner = E::from_request(req, state)
|
let inner = E::from_request(req, state)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ValidRejection {
|
.map_err(|e| ValidRejection {
|
||||||
@@ -391,47 +476,48 @@ where
|
|||||||
response_builder,
|
response_builder,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let args: A = FromRef::from_ref(state);
|
|
||||||
inner
|
inner
|
||||||
.get_validate_args()
|
.get_validate_args()
|
||||||
.validate_args(&args)
|
.validate_args(&arguments)
|
||||||
.map_err(|e| ValidRejection {
|
.map_err(|e| ValidRejection {
|
||||||
error: ValidError::Valid(e),
|
error: ValidError::Valid(e),
|
||||||
response_builder,
|
response_builder,
|
||||||
})?;
|
})?;
|
||||||
Ok(ValidEx(inner, args))
|
Ok(ValidEx(inner, arguments))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<S, E, A> FromRequestParts<S> for ValidEx<E, A>
|
impl<S, E, Arguments> FromRequestParts<S> for ValidEx<E, Arguments>
|
||||||
where
|
where
|
||||||
S: Send + Sync,
|
S: Send + Sync,
|
||||||
|
Arguments: Send + Sync,
|
||||||
E: for<'v> HasValidateArgs<'v> + FromRequestParts<S>,
|
E: for<'v> HasValidateArgs<'v> + FromRequestParts<S>,
|
||||||
for<'v> <E as HasValidateArgs<'v>>::ValidateArgs: ValidateArgs<'v, Args = &'v A>,
|
for<'v> <E as HasValidateArgs<'v>>::ValidateArgs: ValidateArgs<'v, Args = &'v Arguments>,
|
||||||
A: FromRef<S>,
|
ValidationContext<Arguments>: FromRef<S>,
|
||||||
ValidationContext: FromRef<S>,
|
|
||||||
{
|
{
|
||||||
type Rejection = ValidRejection<<E as FromRequestParts<S>>::Rejection>;
|
type Rejection = ValidRejection<<E as FromRequestParts<S>>::Rejection>;
|
||||||
|
|
||||||
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
|
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
|
||||||
let ValidationContext { response_builder }: ValidationContext = FromRef::from_ref(state);
|
let ValidationContext {
|
||||||
|
response_builder,
|
||||||
|
arguments,
|
||||||
|
}: ValidationContext<Arguments> = FromRef::from_ref(state);
|
||||||
let inner = E::from_request_parts(parts, state)
|
let inner = E::from_request_parts(parts, state)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ValidRejection {
|
.map_err(|e| ValidRejection {
|
||||||
error: ValidError::Inner(e),
|
error: ValidError::Inner(e),
|
||||||
response_builder,
|
response_builder,
|
||||||
})?;
|
})?;
|
||||||
let args: A = FromRef::from_ref(state);
|
|
||||||
inner
|
inner
|
||||||
.get_validate_args()
|
.get_validate_args()
|
||||||
.validate_args(&args)
|
.validate_args(&arguments)
|
||||||
.map_err(|e| ValidRejection {
|
.map_err(|e| ValidRejection {
|
||||||
error: ValidError::Valid(e),
|
error: ValidError::Valid(e),
|
||||||
response_builder,
|
response_builder,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(ValidEx(inner, args))
|
Ok(ValidEx(inner, arguments))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user