Learn Server protocol

Your backend can inspect and manipulate Unpoly's rendering through plain HTTP headers: request headers tell the server what Unpoly is about to render, and response headers let the server change what happens on the client. This exchange is Unpoly's server protocol, documented header by header in up.protocol. None of it is required, and you can implement only the parts you need.

Libraries that implement the protocol exist for many languages and frameworks. See Protocol implementations.

What the server can read

Every request that Unpoly makes carries headers describing its purpose. For a link that updates a .menu element in a drawer overlay, the server sees:

GET /sitemap HTTP/1.1
X-Up-Version: 3.15.0
X-Up-Target: .menu
X-Up-Mode: drawer

The frontend's version arrives in X-Up-Version. Its presence alone tells an Unpoly request from a full page load.

The targeted fragment arrives as a CSS selector in X-Up-Target. A server can render only that fragment and skip the rest of the page. When the server responds with an error status, Unpoly renders a different target, which is sent as X-Up-Fail-Target.

The targeted layer is described by X-Up-Mode, the mode of the layer being updated, and X-Up-Fail-Mode for error responses. X-Up-Origin-Mode is the mode of the layer containing the link or form that made the request, in case it targets another layer. A server may render leaner pages for overlays.

The layer's context arrives as JSON in X-Up-Context (and X-Up-Fail-Context), so a server can vary a reused screen by the data a layer was opened with.

Validation requests carry the names of the fields being validated in X-Up-Validate. The server is expected to validate the submission without saving it and to render the form again, as described in Validating forms.

The known version of a reloaded fragment arrives as If-None-Match or If-Modified-Since, so the server can answer with an empty 304 Not Modified when nothing changed. See Conditional requests.

A response that depends on any of these headers should name them in a Vary header, so that Unpoly partitions its cache by their values.

What the server can send

Response headers let the server override what Unpoly would do with the response. All of them are optional. Without them, Unpoly renders the targeted fragment from the response body.

Changing the target. An X-Up-Target response header replaces the selector that Unpoly will render. The value :none finishes the render pass without changes:

HTTP/1.1 200 OK
X-Up-Target: .flashes

<div class="flashes">Your changes were saved.</div>

Setting the document title. When a shortened response has no <title>, an X-Up-Title header sets it. The value is a relaxed JSON string.

Correcting the browser location. After a redirect, Unpoly uses the final URL for the browser's address bar. It cannot see a change of the HTTP method, e.g. when POST /users redirects to GET /users. Send X-Up-Location and X-Up-Method to make the final URL and method explicit:

HTTP/1.1 200 OK
X-Up-Location: /users
X-Up-Method: GET

Emitting events on the client. X-Up-Events takes a relaxed JSON array of event objects. Each object's type becomes the event type, other properties become properties of the event:

HTTP/1.1 200 OK
X-Up-Events: [{ type: 'user:created', id: 5012 }]

Closing or opening overlays. X-Up-Accept-Layer and X-Up-Dismiss-Layer close the targeted overlay with the given result value, instead of rendering the response. X-Up-Open-Layer renders the response in a new overlay. See Subinteractions for the pattern these headers enable.

Updating the layer context. An X-Up-Context response header carries the changed keys. See Changing context from the server.

Controlling the cache. When Unpoly sends a non-GET request, it expires its entire cache. X-Up-Expire-Cache and X-Up-Evict-Cache expire or evict additional cache entries matching a URL pattern:

HTTP/1.1 200 OK
X-Up-Expire-Cache: /notes/*

Versioning content. An ETag or Last-Modified header lets the server answer later reloads with 304 Not Modified. See Conditional requests.

The up.protocol reference lists every header with its exact format.

Other conventions

A few parts of the protocol are not headers:

  • Unpoly sends a CSRF token with unsafe requests, read from a <meta name="csrf-token"> tag. The header name defaults to X-CSRF-Token and is configured in up.protocol.config.csrfHeader.
  • Unpoly sends a request with a method other than GET or POST as a POST, with the original method in a _method parameter. Fragment updates can opt out with up.network.config.wrapMethod.
  • A server can set a _up_method cookie to tell Unpoly the method of the initial page load. This lets Unpoly handle pages that were loaded with a POST request.

A protocol implementation for your framework wraps all of this in helpers. Most handle the _up_method cookie for you, and some, like unpoly-rails, also set the Vary header when you read a request header. See Protocol implementations for the list.