Form extraction — `request.form()`
request.form() is a method built into Request that orchestrates a full pipeline behind the scenes:
request.form() is a method built into Request that orchestrates a full pipeline behind the scenes:
- Sentinel — Checks the route's access rules (
GuardRules: signed in, staff, superuser, groups) against the account read from the database. - Aegis — Single body extraction (multipart, urlencoded, json) normalized into a
HashMap, within the request size limit. For a multipart body, no file is written before a valid CSRF token (X-CSRF-Tokenheader, or acsrf_tokenfield placed before the files). - CSRF Gate — Verifies the CSRF token in parsed data.
- Construction — Builds the form
T, fills fields, and runs validation.
use runique::prelude::*;
pub async fn register(mut request: Request) -> AppResult<Response> {
let form: RegisterForm = request.form();
if let Ok(validated) = ValidationForm::try_new(form, &request).await {
// Valid form → processing
}
// ...
}
💡 The developer simply calls
request.form()— the entire security pipeline is transparent.
Full example — display, validate, save
A single handler serves both display (GET) and submission (POST). request.form() builds the form in both cases: empty on GET, filled from the body on POST.
use runique::prelude::*;
pub async fn register(mut request: Request) -> AppResult<Response> {
let form: RegisterForm = request.form();
let template = "register_form.html";
// GET (nothing submitted) or invalid POST — re-render with errors
let mut validated = match ValidationForm::try_new(form, &request).await {
Ok(validated) => validated,
Err(form) => {
context_update!(request => { "register_form" => &form });
return request.render(template);
}
};
// Valid POST — save
match validated.save(&request.engine.db).await {
Ok(user) => {
success!(request.notices => format!("Welcome {} !", user.username));
return Ok(Redirect::to("/").into_response());
}
Err(err) => {
// DB error (e.g. unique constraint) reported on the form
validated.database_error(&err);
}
}
context_update!(request => { "register_form" => &*validated });
request.render(template)
}
Key points:
request.form()returns a ready-to-use form — no manual construction.ValidationForm::try_new(form, &request).awaitdispatches on the HTTP method (allow_get/allow_post) then validates;Okproves at the type level the form was validated,Errreturns the form with its field errors to re-render (rendered automatically by{{ form.register_form | form }}).validated.save(&request.engine.db).awaitpersists the entity and returns the created model.database_error(&err)reports a DB error (e.g. email already taken) as a form error rather than a 500 — callable directly onValidationFormwithout going throughinto_form().
← Forms | RuniqueForm trait →