Frontend-Backend Protocol
Applin frontends and backends communicate with JSON and HTTP. The protocol incorporates the core concepts of REST.
Pages and URLs
Every Applin app is accessible at a particular base URL
with the form https://HOST/PATH
.
The URL must not contain query or fragment components.
Every Applin app page has a URL. All page URLs are relative to the base URL.
The default "home page" is at relative URL /
.
Applin frontends display pages only from the base URL. They do not fetch pages from other servers or URLs. To display content from another server, have your server fetch the content.
For example, if your app's base URL is https://apps.example.com:1234/travel
then the page /hotels
has URL https://apps.example.com:1234/travel/hotels
.
Frontend Role
Every Applin frontend is a program that makes requests to a particular Applin server, receives page specifications from the server, and provides functions for interacting with pages and navigating between pages.
Request types:
GET
for a page the frontend has not previously requested- Request headers
Accept: application/vnd.applin_response
See Accept on MDN.
- Request headers
GET
to refresh a page that has no variables- Request headers
Accept: application/vnd.applin_response
- Request headers
POST
to refresh a page that has variables (user-input widgets).- Request headers
Accept: application/vnd.applin_response
Content-Type: application/json
request header
- Request body is a JSON object with the current page's variables.
- Request headers
POST
for anrpc
action on a button.- Request headers
Content-Type: application/json
request header
- Request body is a JSON object with the current page's variables.
- Request headers
GET
for page content (images, etc.)
Server Role
Every Applin server is an HTTP server that handles requests.
- Requests for pages, when request has the
Accept: application/vnd.applin_response
header- Response headers
Content-Type: application/vnd.applin_response
- Response code:
200 OK
- Response body is a JSON object with the format described below.
- Do not return 4xx errors for bad user input. Instead, display problems on the page.
- Response headers
- Form POST (without
Accept: application/vnd.applin_response
)- Response code:
200 OK
- No response body
- When the request is missing a required variable, or a variable has the wrong type
- Response code:
400 Bad Request
- Response headers:
Content-Type: text/plain
- Response body: technical details about the problem
- Response code:
- When the user entered data that is unacceptable
- Response code:
422 Unprocessable Content
- Response headers:
Content-Type: text/plain
- Response body: a message for the user
- Response code:
- Response code:
- When the user is not logged in (session cookie missing or invalid) or does not have permission to view the page
- Response code:
403 Forbidden
- Response headers:
Content-Type: text/plain
- Response body: a message for the user
- Response code:
- When the server failed to process the request
- Response code:
500 Internal Server Error
- Response headers:
Content-Type: text/plain
- Response body: technical details about the problem
- Response code:
- When the server is overloaded
- Response code:
503 Service Unavailable
- No response body
- The frontend will retry with backoff.
- Response code:
Applin frontends receive and send cookies like web browsers. Servers can set and receive cookies for session tokens. See Cookies on MDN.
Applin Request Format
The application/json
content-type is a
JSON object encoded in a UTF-8 string.
It contains key-value pairs for all data-entry widgets on the page.
Applin Response Format
The application/vnd.applin_response
content-type is a JSON object encoded in a UTF-8 string.
It must include these keys:
page
is an Applin page specification
Example Exchange
Frontend request:
GET /new_account HTTP/1.1
Server response:
HTTP/1.1 200 OK
Content-Type: application/vnd.applin_response
{
"page": {
"typ": "nav_page",
"title": "New Account",
"widget": {
"typ": "scroll",
"widget": {
"typ": "form",
"widgets": [
{
"typ": "textfield",
"label": "Username",
"var_name": "username"
},
{
"typ": "nav_button",
"text": "Terms",
"actions": [
"push:/terms"
]
},
{
"typ": "nav_button",
"text": "Privacy",
"actions": [
"push:/privacy"
]
},
{
"typ": "checkbox",
"text": "I agree",
"var_name": "agree"
},
{
"typ": "form_button",
"text": "Create Account",
"actions": [
"rpc:/create_account",
"replace_all:/"
]
}
]
}
}
}
}
Frontend shows the page:
User enters user1
in the text box, checks the "I agree" box, and clicks the "Create Account button".
Frontend performs the first action on the button, "rpc:/create_account"
, by sending this request:
POST /create_account HTTP/1.1
content-type: application/json
{"agree":true,"username":"user1"}
Server responds with
HTTP/1.1 200 OK
Frontend receives this successful response and then performs the next action on the button,
"replace_all:/"
, removing all visible pages and showing the home page.