rambler-digital-solutions / actix-web-validator Goto Github PK
View Code? Open in Web Editor NEWRust library for providing validation mechanism to actix-web with Validator crate.
License: MIT License
Rust library for providing validation mechanism to actix-web with Validator crate.
License: MIT License
The error response it gives could be improved, I have the following suggestion:
impl ResponseError for Error {
fn error_response(&self) -> HttpResponse {
HttpResponse::build(StatusCode::UNPROCESSABLE_ENTITY).body(match self {
Self::Validate(e) => {
println!("Validation errors: {:#?}", e);
//convert into ErrorResponse
let mut errors = HashMap::new();
for (field, val_errors) in e.clone().field_errors() {
let mut error_messages: Vec = Vec::new();
for err in val_errors {
if err.message.is_some() {
error_messages.push(err.message.clone().unwrap().to_string());
continue;
}else {
error_messages.push(err.code.to_string());
}
}
errors.insert(field.to_string(), error_messages);
}
let error_response = ErrorResponse{
message: "Validation error".to_string(),
errors
};
serde_json::to_string(&error_response).unwrap()
}
_ => format!("{}", *self),
})
}
}
Hey,
I guess we are doing something wrong, but I can't google it
I have a structure
#[derive(Validate, Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, Apiv2Schema)]
pub struct BalanceRequest {
#[validate(custom = "crate::errors::validate_account_id")]
pub account_id: types::AccountId,
}
And the handler
#[api_v2_operation]
pub async fn get_near_balance(
request: actix_web_validator::Path<schemas::BalanceRequest>,
) -> crate::Result<Json<schemas::NearBalanceResponse>> {
...
}
And, it does not compile, giving 4 similar errors for each handler, saying that I have to implement 4 methods: update_parameter
, update_security
, update_security_definitions
, update_definitions
.
error[E0599]: no function or associated item named `update_parameter` found for struct `actix_web_validator::Path<BalanceRequest>` in the current scope
--> src/modules/coin/resources.rs:10:1
|
10 | #[api_v2_operation]
| ^^^^^^^^^^^^^^^^^^^ function or associated item not found in `actix_web_validator::Path<BalanceRequest>`
|
While googling, I've found no examples of using validator + macro #[api_v2_operation]
Should this combo work at all?
The whole code is here https://github.com/neeeekitos/near-enhanced-api-server
FYI @neeeekitos
Current behaviour is that we just return BAD_REQUEST... However, this is not enough because then we don't know which field(s) failed validation.
Current code:
https://github.com/rambler-digital-solutions/actix-web-validator/blob/master/src/error.rs#L51-L55
If we change this method we can return a list of errors, or at least the first one
Update actix-web dependencies to 2.+
Update tests and documentation.
We need to update docs, provide usage examples and anything more
In my code, I created a function to allow me to write a custom error handler for JSON data validation errors. It includes something like this:
match error {
actix_web_validator::Error::Validate(_) | actix_web_validator::Error::Deserialize(_) => Some(StatusCode::BAD_REQUEST),
// ...more variants...
}
I was expected that any error occurring during JSON deserialization (missing field, etc.) would result in an Error::Deserialize(DeserializeErrors::DeserializeJson(_))
. However, this is not the case - instead, I get an Error::JsonPayloadError(JsonPayloadError::Deserialize(_))
.
I believe this is caused by this code:
actix-web-validator/src/json.rs
Lines 131 to 134 in b8ffc17
In this match
's Err(e)
branch, e
is an actix_web::error::JsonPayloadError
. Thus, Error::from
will use the From
implementation for JsonPayloadError
, resulting in an Error::JsonPayloadError
.
I suppose one possible solution would be to add a match
branch to separate the deserialization errors, something like this:
.map(|res: Result<T, _>| match res {
Ok(data) => data.validate().map(|_| Json(data)).map_err(Error::from),
Err(actix_web::error::JsonPayloadError::Deserialize(e)) => Err(Error::from(e)), // will use From<serde_json::error::Error for Error
Err(e) => Err(Error::from(e)), // will use From<actix_web::error::JsonPayloadError> for Error (like before)
})
Please note that this is hypothetical, I haven't tested the above code at all. π
FWIW, any deserialization error that occurs for Path
or Query
does result in the correct Error::Deserialize(_)
variant being used.
Hi,
this is a feature request.
is it possible somehow users to be able to configure format for validation errors. Now the only format is plain text but I would like JSON format to be an option as well.
I have Actix-Web web services properly responding with HTTP 400 codes and descriptive error message when validation fails for simple use cases. However, when using nested validation (struct with derived Validate containing another struct with derived Validate), the error message returned by Actix-Web-Validator is not very descriptive.
Please consider the following stucts:
#[derive(Serialize, Deserialize, Validate, Debug)]
#[serde(rename_all = "camelCase")]
pub struct SearchParams {
#[validate]
page_params: PageParams,
determine_total_count: bool
}
#[derive(Serialize, Deserialize, Validate, Debug)]
#[serde(rename_all = "camelCase")]
pub struct PageParams {
#[validate(range(min = 0))]
page: u16,
#[validate(range(min = 1, max = 100))]
page_size: u8
}
If I have a web service with input param Json<PageParams> and validation fails, I get a descriptive error message such as this:
Validation errors in fields:
pageSize: range
However, if I have a web service with input param Json<SearchParams> and validation fails on the same page_size field of the PageParams struct (nested validation), then the error message does not indicate which nested field failed validation or why:
Validation errors in fields:
Hello there,
I'm trying out the library to facilitate ease validation error responses.
I've made a struct for create requests:
use serde::{Deserialize, Serialize};
use validator::Validate;
#[derive(Deserialize, Validate, Debug)]
pub struct CreateUser {
#[validate(length(min = 3))]
pub first_name: String,
#[validate(length(min = 3))]
pub last_name: String,
#[validate(email)]
pub email: String,
pub password: String,
}
then in my handler
use actix_web_validator::Json;
use actix_web::error::HttpError;
use actix_web::HttpResponse;
#[actix_web::post("/users")]
pub async fn create(req: Json<CreateUser>) -> Result<HttpResponse, HttpError> {
todo!()
}
but I get the following compile error
the trait `validator::traits::Validate` is not implemented for `CreateUser`
Can you please point what I'm doing wrong. Thanks
Hello !
I'm actually facing an issue while trying to use actix-web-validator
.
I probably have overlooked a simple thing, but to be honest I'm still very new to Rust.
When using Validate
, e.g. :
// src/models.rs
use serde::Deserialize;
use actix_web_validator::Validate;
#[derive(Debug, Deserialize, Clone, Validate)]
pub struct MyStruct {
#[validate(length(min = 3, max = 60))]
pub name: String,
// ...
}
I get the following error π :
pub trait Validate
The trait that validator_derive implements
failed to resolve: could not find `validator` in `{{root}}`
I naively tried to add the following in the root already βοΈ :
// src/lib.rs
#[macro_use]
extern crate actix_web_validator;
// ...
Unsuccessfully π
Thanks in advance for the help you can provide π
Hi, I was using validator 0.11
in my own project and yours uses validator 0.12
. This for some strange reason I encountered a build error where the validator::traits::Validate
trait was not satisfied for one of my struct
s.
The issue ended up being that I was deriving validator 0.11
's Validate
, while FromRequest
on Json
from this crate was using 0.12
.
Please consider a pub use validator::Validate
in this crate so that it is easy to use the same version of the Validate
trait.
It's a good idea to allow stateful custom validators to be used via https://docs.rs/validator/latest/validator/trait.ValidateArgs.html#tymethod.validate_args . This allows injecting custom services/data into validation logic.
ε¦δ½θͺδΉιθ――δΏ‘ζ―οΌ
{
"code":400,
"message":"please input password"
}
or
{
"code":400,
"message":{"password":"please input password","username":"please input username"}
}
Hi,
I tried to compile the following example with Validator 0.15.0 and I got the following error.
#[post("/user/info")]
| ^^^^^^^^^^^^^^^^^^^^^ the trait validator::traits::Validate
is not implemented for Info
This is the example:
use actix_web::{post, web};
use actix_web_validator::Json;
use serde::{Deserialize, Serialize};
use validator::Validate;
#[derive(Deserialize, Serialize, Debug, Validate)]
pub struct Info {
#[validate(length(min = 3, max = 6))]
username: String,
#[validate(email)]
email: String,
password: String,
confirm_password: String,
}
#[post("/user/info")]
pub async fn info(info: Json<Info>) -> web::Json<Info> {
web::Json(Info {
username: info.username.clone(),
email: info.email.clone(),
password: info.password.clone(),
confirm_password: info.confirm_password.clone(),
})
}
The example works just fine with Validator 0.14.0
ValidatedJson should be similar by functionality and interface with https://docs.rs/actix-web/1.0.9/actix_web/web/struct.Json.html
Hello,
I stumbled upon an issue that I can't really understand :
from my understanding, any type that implements validator::Validate
should be automatically validated (as long as it is Some
if inside an Option
) if wrapped in a actix_web_validator::Query
.
logic.rs
// some more imports ...
use validator::{Validate, ValidationError, ValidationErrors}; // here I also tried to switch to actix_web_validator::Validate counterpart, unsuccessfully
#[derive(Deserialize)]
pub struct SomeOrderBy(pub String);
#[derive(Deserialize, Validate)]
pub struct Pagination<T: Validate> {
pub order_by: Option<T>,
}
impl Validate for SomeOrderBy {
fn validate(&self) -> Result<(), ValidationErrors> {
println!("validating for SomeOrderBy");
// validation logic ...
}
}
route.rs
// some more imports ...
use actix_web_validator::Query;
#[get("my-route")]
pub async fn my_route(
query: Query<Pagination<SomeOrderBy>>,
) -> impl Responder {
// route logic ...
}
Given a request with an unknown value for order_by
query parameter, I expect a failed validation which returns an early 400 - Bad Request.
GET /my-route?order_by=unknown
The request is processed as if valid, and the validate
method of SomeOrderBy
is never triggered.
I might have messed up somewhere, if that's the case please provide some additional hints.
Thanks :)
As well as ValidatedQuery exists, there are should be also ValidatedPath with same validation functional
The dependency in Cargo.toml should ideally be:
- actix-web = "3.0.2"
+ actix-web = { version = "3.0.2", default-features = false }
Library functional should be covered by tests
Hello would it be possible to update validator version ?
I face some trait mismatch :/
Thank you
We need to implement the Deref trait for ValidatedQuery and write a test.
Current suggested way is to import json extractor as use actix_web_validator::Json
and ValidatedJson
is deprecated.
The problem with this approach actix::web::Json
used not only as Extractor
, but also as Responder
and usual signature is
pub(crate) async fn create(
req: web::Json<CreateRequest>,
) -> Result<web::Json<CreateResponse>> {}
As a result it can't be in-place replacement and i have use actix_web_validator::Json as ValidatedJson
in near all my endpoints.
I would love if there would be more documentation about error handlers available.
The only thing I found was this comment
For example I went with this:
use actix_web_validator::error::flatten_errors;
use serde::Serialize;
use serde_json::Value;
use std::collections::HashMap;
#[derive(Serialize)]
pub struct ValidationErrorJsonPayload {
pub message: String,
pub fields: Vec<FieldError>,
}
#[derive(Serialize)]
pub struct FieldError {
pub field_name: String,
pub params: HashMap<String, Value>,
}
impl From<&validator::ValidationErrors> for ValidationErrorJsonPayload {
fn from(error: &validator::ValidationErrors) -> Self {
let errors = flatten_errors(error);
let mut field_errors: Vec<FieldError> = Vec::new();
for (index, field, error) in errors {
field_errors.insert(
index as usize,
FieldError {
field_name: field,
params: error.params.clone().into_iter().map(|(key, value)| (key.into_owned(), value)).collect(),
},
)
}
ValidationErrorJsonPayload {
message: "Validation error".to_owned(),
fields: field_errors,
}
}
}
WIth this setup the actual error is getting returned
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.