The handshake is required before any requests can be served. If the first message sent cannot be parsed as a handshake, the connection will be dropped. The handshake will be used to associate the client with a specific user (and set of security rules) on the server. This should be extensible in the same way as #12.
For now let's just leave this a placeholder, since we haven't gotten to authentication yet.
{
"request_id": <NUMBER>,
"method": "unauthenticated" | "anonymous" | "token",
"token": <STRING>,
}
request_idis a number uniquely identifying this request, it will be returned in the response.methoddesignates the type of authentication to be performed.unauthenticatedperforms no further steps and will not associate the connection with any user.anonymouswill create a new account with no external authentication provider.tokenwill associate the connection with the user in the horizon access token provided.
tokenis the horizon access token that the client must already possess.- This field is required when
methodistoken, and invalid otherwise.
- This field is required when
{
"request_id": <NUMBER>,
"token": <STRING>
}
tokenis the horizon access token that is associated with this connection.- This token may be used to establish new connections under the same user account until the token expires.
{
"request_id": <NUMBER>,
"error": <STRING>,
"error_code": <NUMBER>
}
All requests match the following pattern:
{
"request_id": <NUMBER>,
"type": <STRING>,
"options": <OBJECT>
}
request_idis a number uniquely identifying this request, it will be returned in any responsestypeis the endpoint for the query - one ofquery,subscribe,store_error,store_replace,update, orremove.optionsis an object structured differently for each endpoint.
{
"request_id": <NUMBER>,
"type": "query" | "subscribe",
"options": {
"collection": <STRING>,
"order": [ <ARRAY>, "ascending" | "descending"],
"above": [ <OBJECT>, "open" | "closed" ],
"below": [ <OBJECT>, "open" | "closed" ],
"find": <OBJECT>,
"find_all": [<OBJECT>, ...],
"limit": <NUMBER>,
}
}
collectiondescribes which table to operate on in the horizon database.orderorders the results according to an array of fields - optional.- The first argument is an array of field names, most-significant first.
- The second argument determines which direction the results are sorted in.
aboveandbeloware arrays describing the boundaries regardingorder- optional.aboveandbelowcan only be specified iforderis provided.- The first argument is an object whose key-value pairs correspond to fields in
order. - The second argument should be
closedto include the boundary, andopenotherwise.
findreturns one object incollectionthat exactly matches the fields in the object given - optional.findcannot be used withfind_all,order,above, orbelow.
find_allis an array of objects whose key-value pairs correspond to keys inindex- optional.- Returns any object in
collectionthat exactly matches the fields in any of the objects given. find_allcannot be used withfind.find_allwith multiple objects cannot be used withorder,above, orbelow.
- Returns any object in
limitlimits the number of results to be selected - optional.
{
"request_id": <NUMBER>,
"type": "store" | "update" | "upsert" | "insert" | "replace" | "remove",
"options": {
"collection": <STRING>,
"data": [<OBJECT>, ... ]
}
}
collectiondescribes which table to operate on in the horizon databasedatais the documents to be written (or removed)data[i].idis required forremoveoperations, all other fields are optionaldata[i].idmay be omitted in aninsert,store, orupsertoperations: a new row will be inserted in the collection
typeis the write operation to performinsertinserts new documents, erroring if any document already existsupdateupdates existing documents. It errors if any document does not already existupsertupdates existing documents or inserts them if they do not existreplacereplaces existing documents entirely. It errors if any document does not already existstorereplaces existing documents entirely, or inserts them if they don't exist.removeremoves documents. It will not error if a document does not exist
Tells the horizon server to stop sending data for a given subscription. Data may still be received until the server has processed this and sent a "state": "complete" response for the subscription.
{
"request_id": <NUMBER>,
"type": "end_subscription"
}
This is used by the client to perform an empty request to avoid connection interruption.
{
"request_id": <NUMBER>,
"type": "keepalive"
}
This can be sent for any request at any time. Once an error response is sent, no further responses shall be sent for the corresponding request_id.
{
"request_id": <NUMBER>,
"error": <STRING>,
"error_code": <INTEGER>
}
request_idis the same as therequest_idin the corresponding requesterroris a descriptive error stringerror_codeis a code that can be used to identify the type of error, values TBD
query and subscribe requests will result in a stream of results from the horizon server to the client. The stream will be an ordered set of messages from the server following the structure below. If an error occurs, the above Error Response structure will be used, and the stream is considered "complete". An Error Response may still be sent even after a successful data response, but not after "state": "complete".
{
"request_id": <NUMBER>,
"data": <ARRAY>,
"state": "synced" | "complete"
}
request_idis the same as therequest_idin the corresponding requestdatais an array of results for thequeryorsubscribe, and may be emptystateis optional, and indicates a change in the stream of data:syncedmeans that following the consumption ofdata, the client has all the initial results of asubscribecompletemeans that following the consumption ofdata, no more results will be returned for the request
store, replace, insert, update, upsert, and remove requests will be given a single response. This may be an Error Response, or:
{
"request_id": <NUMBER>,
"data": [ { "id": <DOCUMENT_ID>, "$hz_v$": <DOCUMENT_VERSION> } | { "error": <STRING>, "error_code": <INTEGER> }, ...],
"state": "complete"
}
datais an array of objects corresponding to the documents specified in the write (whether or not a change occurred). For inserted documents it will be the id generated by the server as well as the latest version field for the affected document. If an error occurred, there will instead be an error description string and an error code in the object . The items in the array correspond directly to the changes in the request, in the same order.statecan only be "complete" for write responses
keepalive requests will be given a single response. This will never be an error response unless there is a protocol error.
{
"request_id": <NUMBER>,
"state": "complete"
}