Protocol Overview

POSTAL is a message based protocol with structured messages encoded using transit+json serialization format.

Warning
this document is under design and is considered in pre-alpha state.

Rationale

The tipical web application usually follows the REST API architecture, but the main problem of that is that is bound directly to the HTTP semantics that are not always coherent or not always clear how to use.

The main goal of this protocol is to put aside the REST API semantics and build own ones on top of the HTTP protocol. Allowing to build rich and powerful API’s without any restrictions of the the REST API’s.

The general idea is borrowed from Facebook Relay. So it is an ideal protocol for building declarative data-fetching apps and using this transport protocol for client-server communication.

Messages

A postal message consists of a structured data serialized using transit+json. This is how a message looks like:

{:type :query
 :dest :users
 :data {:some :data}}

The previus message looks like this when it is encoded using transit+json serialization format:

"[\"^ \",\"~:type\",\"~:query\",\"~:dest\",\"~:users\",\"~:data\",[\"^ \",\"~:some\",\"^4\"]]"

postal comes with a set of predefined types of messages with specified semantics but that doesn’t limit the user to define their own messages on top of the protocol.

Common Messages

:response

This is a generic message that represents a server response to some kind of request.

This is how a :response message looks like:

{:type :response
 :data {:id 1, :firstname "Yennefer"}}

:error

It’s a generic message that represents an error situation. This kind of messages can be sent by a server when something goes wrong.

This how an :error message looks like:

{:type :error
 :data {:message "Does not exists"}}

:message

This is a generic message that represents a server push notification and its aspect is almost identical to the :response but has very different semantics.

This message type can be sent by server in some kind of subscriptions using long polling HTTP requests. The transport layer for this kind of messages is explicitly undefined.

This is how this message looks like:

{:type :message
 :data {:id 1, :firstname "Yennefer"}}

REQ/REP

This section will explain messages defined for request/reply pattern.

:query

This is a message that should be used for requesting data from a specified resource. It is analogous to the HTTP GET.

This is how a :query message looks like:

{:type :query
 :dest :users
 :data {:id 2}}

After sending a :query message we should expect an :response message to be sent back or :error if an error has ocurred. The :dest property is mandatory.

:novelty

This is a message that is used to submit data to be processed by a specified resource. It is analogous to the HTTP POST/PUT.

This how a :novelty message looks like:

{:type :novelty
 :dest :users
 :data [[:db/add 857582744 :username "foobar"]
        [:db/add 857582744 :password "secret"]]}

After sending a :novelty message we should expect a :response message to be sent back or :error if an error has ocurred. The :dest property is mandatory.

PUSH/PULL

This section will explain messages defined for push/pull pattern. In other words it allows to implement a queue like communication.

PUT

This is a message that should be used for puting the data to the server.

This is how a :put message looks like:

{:type :put
 :dest :some-queue
 :data {:id 2}}

After sending a :put message we should expect a :response message to be sent back or :error if an error has ocurred. The :dest property is mandatory.

Note
the server behavior is specifically not defined. It can just not block and return a response or block the HTTP connection (without clossing it) until the message is accepted.

TAKE

This is a message that should be used for geting the data from server.

This is how a :take message looks like:

{:type :take
 :dest :some-queue}

After sending a :take message we should expect a :response message to be sent back or :error if an error has ocurred. The :dest property is mandatory.

Note
the server behavior is specifically not defined. It can just not block and return a response or block the HTTP connection (not clossing it) until the message is available.

PUB/SUB

This section will explain messages defined for publish/subscribe pattern.

:subscribe

This is a message that should be used for notifying the server that a client wants to subscribe to a specific topic.

{:type :subscribe
 :dest :user/notification
 :data {:id 2}}

The behavior of the backend and the transport layer is explicitly undefined. The most basic approach is to just do a long-polling or using server sent events.

:publish

This is a message that should be used for publishing a message to a specified topic. If a client is subscribed to the topic, it will receive the published message.

{:type :publish
 :dest :user/notification
 :data {:foo "bar"}}

After sending a :publish message we should expect a :response message to be sent back or :error if an error has ocurred. The :dest property is mandatory.

Clients & Servers

Recommendations

Start using HTTP2/SPDY

As this protocol is designed to work on top of HTTP, is highly recommended to deploy your application using HTTP2 or SPDY. It is not necesary that you application server supports it, most of the HTTP proxies such as Nginx aready have support for SPDY and/or HTTP2.

HTTP2/SPDY offers connection multiplexing, allowing to use a unique persistent connection to handle all required context, completly eliminating the overhead of creating and destroyng connections. With that you can make multiple and repeated HTTP connections without performance issues.

License

This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.

In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

For more information, please refer to <http://unlicense.org/>