Konrad Kowalski (rootsher)Principal Platform & Reliability Architect000011010001011100001110111000100100000100110011

HTML Forms: Backend Communication Without JavaScript

date
category
Frontend
also in
Backend
reading
2 min / 329 words

The simplest possible frontend can talk to a backend without a single line of JavaScript. A form is enough.

html
<form method="post" action="/users">
  <input name="name">
  <button type="submit">Create</button>
</form>

When the button is clicked, the browser performs a few very specific steps:

  1. it collects the controls belonging to the form,
  2. it encodes their values,
  3. it builds an HTTP request,
  4. it sends it to action,
  5. it receives the response,
  6. it treats that response as a new document navigation.

This matters: a form is not an "API helper". It is part of the browser's navigation mechanism.

GET and POST

For:

html
<form method="get" action="/search">
  <input name="q" value="http">
</form>

the browser will produce:

http
GET /search?q=http HTTP/1.1
Host: example.com

The data goes into the query string.

For:

html
<form method="post" action="/users">

the values go into the body:

http
POST /users HTTP/1.1
Content-Type: application/x-www-form-urlencoded

name=Alice

The default form encoding is:

text
application/x-www-form-urlencoded

Files usually require:

html
<form method="post" enctype="multipart/form-data">

The body then consists of parts separated by a boundary.

The request causes navigation

The most important property of a classic form is today also its limitation.

After a response like:

http
HTTP/1.1 200 OK
Content-Type: text/html

the browser replaces the current document with the new HTML.

That gives a very simple model:

text
document
  |
  v submit
HTTP request
  |
  v
backend
  |
  v
HTML response
  |
  v
new document

Any UI state that exists only in the DOM or in the JavaScript runtime disappears together with the document.

Redirect after POST

If the backend returns HTML straight after creating a resource, refreshing the page can perform the POST again.

Hence the classic Post/Redirect/Get pattern:

text
POST /users
  |
  v
303 See Other
Location: /users/123
  |
  v
GET /users/123

The backend mutates only in POST, and the final document is loaded with a GET.

This is still one of the cleanest models of handling forms.

What does a form actually solve?

A form ties three things together:

text
UI state
+ serialization
+ navigation

The browser itself:

  • collects the data,
  • encodes the request,
  • handles cookies,
  • sends the request,
  • interprets the response,
  • updates the navigation history.

The price is obvious: every backend interaction can mean loading a whole document.

For the document nature of the web that was enough. For interfaces that resemble desktop applications it was not.

What was needed was a way to perform an HTTP request without navigation.

And that is exactly what AJAX changed.