Giter Site home page Giter Site logo

rambler-digital-solutions / actix-web-validator Goto Github PK

View Code? Open in Web Editor NEW
92.0 10.0 22.0 129 KB

Rust library for providing validation mechanism to actix-web with Validator crate.

License: MIT License

Rust 100.00%
actix-web validator rust validation

actix-web-validator's Introduction

actix-web-validator Latest Version Documentation Coverage Build Status

This crate is a Rust library for providing validation mechanism to actix-web with Validator crate

Installation

This crate works with Cargo and can be found on crates.io with a Cargo.toml like:

[dependencies]
actix-web-validator = "5.0.1"
validator = { version = "0.16", features = ["derive"] }
serde = { version = "1", features = ["derive"] }

Supported extractors:

  • actix_web::web::Json
  • actix_web::web::Query
  • actix_web::web::Path
  • actix_web::web::Form
  • serde_qs::actix::QsQuery

Supported actix_web versions:

  • For actix-web-validator 0.* supported version of actix-web is 1.*
  • For actix-web-validator 1.* supported version of actix-web is 2.*
  • For actix-web-validator 2.* supported version of actix-web is 3.*
  • For actix-web-validator 3+ supported version of actix-web is 4.*

Example:

use actix_web::{web, App};
use serde::Deserialize;
use actix_web_validator::Query;
use validator::Validate;

#[derive(Debug, Deserialize)]
pub enum ResponseType {
    Token,
    Code
}

#[derive(Deserialize, Validate)]
pub struct AuthRequest {
    #[validate(range(min = 1000, max = 9999))]
    id: u64,
    response_type: ResponseType,
}

// Use `Query` extractor for query information (and destructure it within the signature).
// This handler gets called only if the request's query string contains a `id` and
// `response_type` fields.
// The correct request for this handler would be `/index.html?id=1234&response_type=Code"`.
async fn index(info: Query<AuthRequest>) -> String {
    format!("Authorization request for client with id={} and type={:?}!", info.id, info.response_type)
}

fn main() {
    let app = App::new().service(
        web::resource("/index.html").route(web::get().to(index))); // <- use `Query` extractor
}

License

actix-web-validator is licensed under MIT license (LICENSE or http://opensource.org/licenses/MIT)

actix-web-validator's People

Contributors

andreyermilov avatar bricklou avatar c650 avatar dependabot[bot] avatar nixypanda avatar rlebran avatar roms1383 avatar roxe322 avatar singulared avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

actix-web-validator's Issues

Can't use #[api_v2_operation] + actix_web_validator::Path

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

Return validation error in a format that can be processed on the frontend

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),
})
}
}

no default features for actix-web

The dependency in Cargo.toml should ideally be:

- actix-web = "3.0.2"
+ actix-web = { version = "3.0.2", default-features = false }

Update validator version

Hello would it be possible to update validator version ?
I face some trait mismatch :/

Thank you

Update docs

We need to update docs, provide usage examples and anything more

Error::Deserialize(DeserializeErrors::DeserializeJson) is never actually used

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:

.map(|res: Result<T, _>| match res {
Ok(data) => data.validate().map(|_| Json(data)).map_err(Error::from),
Err(e) => Err(Error::from(e)),
})

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.

Write tests

Library functional should be covered by tests

Provide Path validator

As well as ValidatedQuery exists, there are should be also ValidatedPath with same validation functional

Errors in JSON format

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.

Name conflict with actix::web::Json

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.

Nested Validation Error Output

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:

Problem using derive Validate

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.

issue

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 πŸ˜…

context

  • rustc 1.49.0 (e1884a8e3 2020-12-29)
  • platform : MacOS BigSur 11.1
  • actix-web-validator 2.0.3
  • actix-web : 3

Thanks in advance for the help you can provide πŸ˜ƒ

Compatibility with Validator v. 0.15.0

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

Validator version issues cause Compiler Error

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 structs.

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.

validator::traits::Validate is not implemented

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

Validate not triggered

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.

Context

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 ...
}

Expected

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

Got

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 :)

Some or more documentation about custom error handlers.

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

how to custom error message

如何θ‡ͺδΉ‰ι”™θ――δΏ‘ζ―οΌŸ
{
"code":400,
"message":"please input password"
}
or
{
"code":400,
"message":{"password":"please input password","username":"please input username"}
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.