actix-web-validation 0.1.1

A common validation interface for actix-web applications
Documentation

Actix Web Validation

Request validation for actix-web.

WARNING

This library is currently in early access and may recieve breaking changes.

Supported Validation Libraries

Usage

Any type that implments the Actix FromRequest trait can be automatically validated.

# Cargo.toml
actix-web-validation = { version = "0.0.0", features = ["validator"]}
# or 
actix-web-validation = { version = "0.0.0", features = ["garde"]}
use actix_web_validation::validator::Validated;
use validator::Validate;

// or for garde
// use actix_web_validation::garde::Validated;
// use garde::Validate;

// Do validation using your validation library
#[derive(Debug, Validate, Deserialize)]
struct Example {
    #[validate(length(min = 3))]
    name: String,
}

// Wrap your Actix extractor with `Validated` to automatically run validation
#[post("/")]
async fn hello(Validated(Json(payload)): Validated<Json<Example>>) -> impl Responder {
    HttpResponse::Ok().body(format!("Hello {}", payload.name))
}

Custom Errors

Custom error responses can achieved by providing an error handler.

Below is an example custom error response that responds with JSON

#[derive(Debug, Serialize, Error)]
struct CustomErrorResponse {
    custom_message: String,
    errors: Vec<String>,
}

// impl Display for CustomErrorResponse { ... }

impl ResponseError for CustomErrorResponse {
    fn status_code(&self) -> actix_web::http::StatusCode {
        actix_web::http::StatusCode::BAD_REQUEST
    }

    fn error_response(&self) -> HttpResponse<actix_web::body::BoxBody> {
        HttpResponse::build(self.status_code()).body(serde_json::to_string(self).unwrap())
    }
}

Below is an example for the validator crate

fn error_handler(errors: ::validator::ValidationErrors, req: &HttpRequest) -> actix_web::Error {
    CustomErrorResponse {
        custom_message: "My custom message".to_string(),
        errors: errors
            .errors()
            .iter()
            .map(|(err, _)| err.to_string())
            .collect(),
    }
    .into()
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .validator_error_handler(Arc::new(error_handler))
            // ....
    })
    .bind(("127.0.0.1", 8080))?
    .run()
    .await
}

Below is an example for the garde crate

fn error_handler(errors: ::garde::Report, req: &HttpRequest) -> actix_web::Error {
    CustomErrorResponse {
        custom_message: "My custom message".to_string(),
        errors: errors.iter().map(|(_, err)| err.to_string()).collect(),
    }
    .into()
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .garde_error_handler(Arc::new(error_handler))
            // ....
    })
    .bind(("127.0.0.1", 8080))?
    .run()
    .await
}

Motivations

This library is heavily inspired by Spring Validation and actix-web-validator.

The actix-web-validator is great but there are a few pain points I would like to address with this library.

  • More explict validation by using the Validated extractor to reduce the risk of using the wrong Json/Query/ect extractor by mistake.
  • Provide a common interface for validation libraries that can be extended as the Rust ecosystem evolves.