Rocket icon indicating copy to clipboard operation
Rocket copied to clipboard

Validate non form-encoded body content

Open Flying-Toast opened this issue 2 years ago • 2 comments

Rocket has validation for Forms (rocket::form::validate), but when accepting other body content (e.g. JSON), there is no way to validate fields of the Deserialized object, e.g.

#[derive(Deserialize)]
struct Polygon {
    // if this were a FromForm, we could do `#[field(validate = range(3..)]`
    num_sides: u32,
}

#[post("/submit-polygon", data = "<polygon>")]
fn submit(polygon: Json<Polygon>) -> String {
    format!("polygon has {} sides", polygon.num_sides)
}

Polygons shouldn't be allowed to have less than 3 sides, but there is no simple way to enforce this. Ideally we could do something similar to form validation, with field attributes.

Why this feature can't or shouldn't live outside of Rocket

This could possibly be implemented outside of Rocket using some Validate derive and a Valid<T> guard that will only pass if validation succeeds, but that is less than ideal.

Ideal Solution

Ideally, the form-validation logic could be pulled out into its own independent trait, so that you can derive it on any type:

use rocket::Validated;

#[derive(Deserialize, Validated)]
struct Polygon {
    #[validate(range = (3..))]
    num_sides: u32,
}

// would also work on forms:
#[derive(FromForm, Validated)]
struct FooForm<'a> {
    #[validate(omits = "password")]
    password: &'a str,
}

Flying-Toast avatar Sep 23 '21 15:09 Flying-Toast

Polygons shouldn't be allowed to have less than 3 sides, but there is no simple way to enforce this. Ideally we could do something similar to form validation, with field attributes.

Yeah, there's nothing as simple as rocket's field attribute, but for posterity, the likely most straightforward approach would be to use serde's deserialize_with field attribute.

In general, I have some ideas about how to improve/unify data input/output that would include unifying validation across all data handled by a Rocket application. My hope is to write down a spec for the idea soon. Until then, consider this accepted.

SergioBenitez avatar Sep 25 '21 00:09 SergioBenitez

Related https://github.com/SergioBenitez/Rocket/discussions/2110.

IniterWorker avatar Apr 08 '22 00:04 IniterWorker