Rapina uses the Validated<T> extractor to validate incoming requests. If validation fails, it automatically returns a 422 Unprocessable Entity response with details about what went wrong — your handler never runs.
Validation rules are declared on your request struct using the validator crate's derive macros:
#[derive(Deserialize, Validate, JsonSchema)]
struct CreateUserRequest {
#[validate(length(min = 1, max = 100))]
name: String,
#[validate(email)]
email: String,
}Then wrap your extractor with Validated:
async fn handler(Validated(Json(body)): Validated<Json<CreateUserRequest>>)Validate derive to CreateUserRequest#[validate(length(min = 1))] to name and #[validate(email)] to emailJson(body) to Validated(Json(body)) with Validated<Json<CreateUserRequest>>use rapina::prelude::*;
#[derive(Deserialize, Validate, JsonSchema)]
struct CreateUserRequest {
#[validate(length(min = 1, max = 100))]
name: String,
#[validate(email)]
email: String,
}
#[derive(Serialize, JsonSchema)]
struct CreateUserResponse {
id: u64,
name: String,
}
#[public]
#[post("/users")]
async fn create_user(
Validated(Json(body)): Validated<Json<CreateUserRequest>>,
) -> Json<CreateUserResponse> {
Json(CreateUserResponse {
id: 1,
name: body.name,
})
}