Forms & actions
The server reads request bodies and handles plain HTML form submissions — no client framework required. A form works with JavaScript disabled; that's the progressive-enhancement baseline the framework is built on.
Reading the body
Every handler receives the parsed request. The body is read from the socket using Content-Length (capped at 8 MiB) and exposed on the request:
req.body— the raw bytes (Vec<u8>).req.body_str()— the body as lossy UTF-8 text.req.content_length()— the declared length, if any.
GET requests and any request without a Content-Length have an empty body.
Parsing a form
The akurai_http::form module parses application/x-www-form-urlencoded — what a browser submits for <form method="post"> — with percent-decoding and + meaning space:
let pairs = akurai_http::form::parse_urlencoded(&req.body_str());
let name = akurai_http::form::field(&pairs, "name").unwrap_or("");
The Post/Redirect/Get pattern
A submission should validate, act, and then redirect to a GET, so a browser refresh never resubmits:
if name.is_empty() {
return render_form_with_error(...); // re-render, keep what they typed
}
store.append(&record)?; // do the work
Response::new(303).with_header("Location", "/guestbook") // redirect back
Worked example: the guestbook
The live /guestbook is the full pattern end to end:
GET /guestbooklists entries.POST /guestbookvalidates that name and message are present, stores the
entry (durably — see Storage), and 303-redirects to the list.
- On a validation error it re-renders the form with the message and the values
already typed.
Safety
User input rendered with {{ }} is HTML-escaped by the template engine, so a submitted <script> shows as text, not markup. Use {{{ }}} only for content you trust to be safe HTML.