PRG pattern
Post/Redirect/Get — avoid duplicate form submissions after #[submit].
LIVE
PRG submit
Why
After a successful POST, redirect to a GET URL so refresh does not re-submit the form.
Return a redirect
#[submit]
async fn create_item(form: ItemForm, _req: &FlowRequest) -> Result<Redirect, SubmitError> {
db::insert(&form).await.map_err(|_| SubmitError::new("Failed"))?;
Ok(redirect("/items"))
}
// Flash message on the target page (query param `flash=…`):
Ok(redirect_with_flash("/items", "Item created"))
// Or any serializable struct with a `redirect` field:
#[data]
struct CreateResult { redirect: String }
#[submit]
async fn create_alt(form: ItemForm, _req: &FlowRequest) -> Result<CreateResult, SubmitError> {
Ok(CreateResult { redirect: "/items".into() })
}Behavior
- With JavaScript — runtime reads
redirectfrom the JSON response and navigates via SPA fetch (same-origin paths). - Without JavaScript — server responds with 303 See Other and
Locationheader. - Security — only root-relative paths (
/items) are allowed; open redirects are rejected.
Flash messages
Use redirect_with_flash(path, message) — the target page reads it with flash_message(&req). See also Query params for manual flags like ?created=1.