5 releases

0.2.0 Feb 13, 2024
0.1.4 Feb 13, 2024
0.1.3 Oct 3, 2022
0.1.2 Jul 28, 2022
0.1.0 Mar 20, 2022

#1578 in Web programming

Download history 234/week @ 2024-07-20 291/week @ 2024-07-27 250/week @ 2024-08-03 99/week @ 2024-08-10 380/week @ 2024-08-17 521/week @ 2024-08-24 340/week @ 2024-08-31 505/week @ 2024-09-07 737/week @ 2024-09-14 232/week @ 2024-09-21 254/week @ 2024-09-28 658/week @ 2024-10-05 462/week @ 2024-10-12 456/week @ 2024-10-19 410/week @ 2024-10-26 1010/week @ 2024-11-02

2,422 downloads per month
Used in 3 crates (via open-stock)

MIT license

19KB
121 lines

Rocket Validation

Welcome to the Rocket Validation crate. If you are looking to validate your Json, Form or Query structs using Rocket you have come to the right place!

Why

Rocket is using Rusts powerful typing system. Which is amazing because you can be sure its what you want. But is it? How about kebab-case strings or phone number inputs, these aren’t really types. You could implement a custom deserializer for a wrapped type or write custom logic to validate it on endpoint calls, thats error prone and not ergonomic and doesn't allow you to return meaningful and contextual errors.

If you are coming from TypeScript you might have heard of class-validator which is simple, declarative and can be implemented into middleware. Using validator this crate achieves a similar result using rockets guard mechanism.

Anything implementing Json, FromRequest or FromForm as well as Validate are able to use the Validated guard of this crate, so you can be sure your data is validated once you receive it in your handler.

Using rockets catchers you are able to route errors which occurs during validation to your user.

Current validation in rocket: Rocket has validation for FromForm structs but for nothing else.

Usage

In order to get going, you need to depend on the rocket-validation. Add this to your Cargo.toml

[dependencies]
rocket-validation = "0.1.3"
validator="?"

validator is needed as the derive macros of the crate validator generate code dependent on it being available in a global scope

Now you can go on and implement your Validation

// Because we use rocket....
#[macro_use]
extern crate rocket;

// Some types for Json types
use rocket::serde::{json::Json, Deserialize, Serialize};

// Will be important for validation....
use rocket_validation::{Validate, Validated};

#[derive(Debug, Deserialize, Serialize, Validate)] // Implements `Validate`
#[serde(crate = "rocket::serde")]
pub struct HelloData {
	#[validate(length(min = 1))] // Your validation annotation
	name: String,
	#[validate(range(min = 0, max = 100))] // Your validation annotation
	age: u8,
}

#[post("/hello", format = "application/json", data = "<data>")]
fn validated_hello(data: /*Uses the `Validated` type*/ Validated<Json<HelloData>>) -> Json<HelloData> {
	Json(data.into_inner())
}

#[launch]
fn rocket() -> _ {
	rocket::build()
		.mount("/", routes![validated_hello])
}

Exposing errors to clients

Before you use the following, you should be aware of what errors you expose to your clients as well as what that means for security.

If you would like to respond invalid requests with some custom messages, you can implement the validation_catcher catcher to do so.

#[launch]
fn rocket() -> _ {
	rocket::build()
		.mount("/", routes![validated_hello])
		.register("/", catchers![rocket_validation::validation_catcher])
}

Currently limited to Json or FromData validations due to inernal rocket limitations

Dependencies

~21–52MB
~1M SLoC