I am new to rust (4 months) and new to axum and/or its frameworks (validator).
I am creating a web service with Axum and want to validate a simple payload as this.
#[derive(Debug, Deserialize, Validate)]
pub struct RegistrationData {
#[validate(length(min = 3, message = "Username is required"))]
pub username: String,
#[validate(email(message = "Invalid email address"))]
pub email: String,
#[validate(length(min = 6, message = "Password is required"))]
pub password: String,
}
I am implementing from_request
fn to read the body and deserialize it into struct.
#[async_trait]
impl<B> FromRequest<B> for RegistrationData
where
B: Send + Sync,
{
type Rejection = (StatusCode, Json<Value>);
async fn from_request(req: Request, state: &B) -> Result<Self, Self::Rejection> {
let body = Bytes::from_request(req, state)
.await
.map_err(|err| (StatusCode::BAD_REQUEST, Json(json!(err.to_string()))))?;
let registration_data_result: Result<RegistrationData, serde_json::Error> =
serde_json::from_slice(&body);
...
}
}
After this, I am trying to put the logic for validation, but there is a problem. It is sort of working fine, but any missing fields in payload are handled by serde_json::from_slice
itself and hence the below match code always goes to error arm. As a result, the fn registration_data.validate() would get called only if the incoming json has all mandatory fields filled in.
match registration_data_result {
Ok(registration_data) => {
// Perform validation on the deserialized struct
println!(
"Registration Data b4 .validate() call: {:?}",
registration_data
);
if let Err(validation_errors) = registration_data.validate() {
let json_errors = validation_errors_to_json(validation_errors);
return Err((
StatusCode::BAD_REQUEST,
Json(json!({ "errors": json_errors })),
));
}
// If no validation errors, return the deserialized and validated struct
println!("Registration Data: {:?}", registration_data);
return Ok(registration_data);
}
Err(err) => {
return Err((
StatusCode::ACCEPTED,
Json(json!({"error": err.to_string()})),
));
}
The problem is that serde messages aren’t user friendly and appear very technical.
“error”: “missing field ’email’ at line 3 column 1”.
Secondly, all errors won’t come in the response at one go… For example, if the missing field email is provided, then the response asks for another missing field and so on.
To overcome these troubles, I just wanna take the incoming json, feed it to the validator module and get the results.
Thanks for helping me on this.