AkurAI Build
Menu

Public repository / 91bd2a37654909c5a3aef6ddd614991bd378ccb8

AkurAI-Framework / site/content/docs/forms.md

Latest change 0ebc2057fd9a65182855334c219522ae944ad484 - docs: /docs guides for routing, forms, storage, middleware, SEO, styling + dev server by Ólafur Búi Ólafsson

# 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:

```rust
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:

```rust
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 /guestbook` lists entries.
- `POST /guestbook` validates that name and message are present, stores the
  entry (durably — see [Storage](/docs/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.