vld-ntex 0.3.0

ntex integration for the vld validation library — validated extractors for JSON, query, path, form, headers, cookies
Documentation

Crates.io docs.rs License Platform GitHub issues GitHub stars

vld-ntex

ntex integration for the vld validation library.

Overview

Provides 6 extractors that validate request data using vld schemas before your handler runs:

Extractor Replaces Source
VldJson<T> ntex::web::types::Json<T> JSON request body
VldQuery<T> ntex::web::types::Query<T> URL query parameters
VldPath<T> ntex::web::types::Path<T> URL path parameters
VldForm<T> ntex::web::types::Form<T> URL-encoded form body
VldHeaders<T> manual header extraction HTTP headers
VldCookie<T> manual cookie parsing Cookie values

On validation failure all extractors return 422 Unprocessable Entity with a JSON body describing every issue.

Installation

[dependencies]
vld = "0.1"
vld-ntex = "0.1"
ntex = "3"

VldJson — JSON body

use ntex::web::{self, HttpResponse};
use vld_ntex::VldJson;

vld::schema! {
    #[derive(Debug)]
    pub struct CreateUser {
        pub name: String => vld::string().min(2).max(50),
        pub email: String => vld::string().email(),
    }
}

async fn create_user(body: VldJson<CreateUser>) -> HttpResponse {
    HttpResponse::Ok().body(format!("Created: {}", body.name))
}

VldQuery — query parameters

Values are automatically coerced: "42" → number, "true"/"false" → boolean, empty → null.

use ntex::web::HttpResponse;
use vld_ntex::VldQuery;

vld::schema! {
    #[derive(Debug)]
    pub struct SearchParams {
        pub q: String => vld::string().min(1).max(200),
        pub page: Option<i64> => vld::number().int().min(1).optional(),
        pub limit: Option<i64> => vld::number().int().min(1).max(100).optional(),
    }
}

async fn search(params: VldQuery<SearchParams>) -> HttpResponse {
    HttpResponse::Ok().body(format!("Searching '{}' page={:?}", params.q, params.page))
}

VldPath — path parameters

use ntex::web::{self, HttpResponse};
use vld_ntex::VldPath;

vld::schema! {
    #[derive(Debug)]
    pub struct UserPath {
        pub id: i64 => vld::number().int().min(1),
    }
}

async fn get_user(path: VldPath<UserPath>) -> HttpResponse {
    HttpResponse::Ok().body(format!("User #{}", path.id))
}

// Register: .route("/users/{id}", web::get().to(get_user))

VldForm — URL-encoded form body

use ntex::web::HttpResponse;
use vld_ntex::VldForm;

vld::schema! {
    #[derive(Debug)]
    pub struct LoginForm {
        pub username: String => vld::string().min(3).max(50),
        pub password: String => vld::string().min(8),
    }
}

async fn login(form: VldForm<LoginForm>) -> HttpResponse {
    HttpResponse::Ok().body(format!("Welcome, {}!", form.username))
}

VldHeaders — HTTP headers

Header names are normalised to snake_case: Content-Typecontent_type, X-Request-Idx_request_id.

use ntex::web::HttpResponse;
use vld_ntex::VldHeaders;

vld::schema! {
    #[derive(Debug)]
    pub struct AuthHeaders {
        pub authorization: String => vld::string().min(1),
        pub x_request_id: Option<String> => vld::string().optional(),
    }
}

async fn protected(headers: VldHeaders<AuthHeaders>) -> HttpResponse {
    HttpResponse::Ok().body(format!("auth={}", headers.authorization))
}

VldCookie — cookies

Cookie names are matched as-is to schema field names.

use ntex::web::HttpResponse;
use vld_ntex::VldCookie;

vld::schema! {
    #[derive(Debug)]
    pub struct Session {
        pub session_id: String => vld::string().min(1),
        pub theme: Option<String> => vld::string().optional(),
    }
}

async fn dashboard(cookies: VldCookie<Session>) -> HttpResponse {
    HttpResponse::Ok().body(format!("session={}", cookies.session_id))
}

Combining extractors

Multiple extractors can be used in the same handler:

use ntex::web::HttpResponse;
use vld_ntex::{VldJson, VldQuery};

vld::schema! {
    #[derive(Debug)]
    pub struct OrderQuery {
        pub dry_run: Option<bool> => vld::boolean().optional(),
    }
}

vld::schema! {
    #[derive(Debug)]
    pub struct OrderBody {
        pub product_id: i64 => vld::number().int().min(1),
        pub quantity: i64 => vld::number().int().min(1).max(1000),
    }
}

async fn create_order(
    query: VldQuery<OrderQuery>,
    body: VldJson<OrderBody>,
) -> HttpResponse {
    HttpResponse::Ok().body(format!(
        "product={} qty={} dry_run={:?}",
        body.product_id, body.quantity, query.dry_run,
    ))
}

Running the example

cargo run -p vld-ntex --example ntex_basic

Example requests

# VldJson — create user:
curl -s -X POST http://localhost:8080/users \
  -H "Content-Type: application/json" \
  -d '{"name": "Alice", "email": "alice@example.com", "age": 30}'

# VldPath — get user by id:
curl -s http://localhost:8080/users/42

# VldQuery — search:
curl -s "http://localhost:8080/search?q=rust&page=1"

Error response format

{
  "error": "Validation failed",
  "issues": [
    { "path": "name", "message": "String must contain at least 2 character(s)", "code": "too_small" }
  ]
}

License

MIT