-
Notifications
You must be signed in to change notification settings - Fork 0
Protocol
The protocol is very simple. A bundler is attached to an endpoint /bundle by default. It receives an array of options by PUT method as JSON. options can be objects described below, URLs as strings, or a mix of both.
It verifies a bundle (all URLs should be whitelisted, empty payload, and big payloads are rejected, and so on). If everything is alright, it issues I/O requests (usually in parallel), collects responses and sends back a JSON object of the following format:
{
"bundle": "bundle",
"results": [
// a list of result items
]
}Every result item has a following structure:
{
"options": {"url": "/abc"}, // options object
"response": {
"status": 200, // an HTTP status code
"statusText": "OK", // an HTTP status text corresponding to status code
"responseType": "", // taken from options.responseType, or an empty string
"responseText": "[1,2,3]", // a payload as a string
"headers": "Content-Type: application/json" // raw headers
}
}If options is a string, it is assumed to be a URL for a GET request. Otherwise, following properties are recognized:
-
urlis the only required property. It is a URL of an endpoint we deal with.
The rest of properties are all optional with reasonable defaults:
-
methodis an HTTP method (including PATCH) as a string. Default:'GET'. -
queryis a query dictionary (a key/value hash), which is used to form a query part of URL after'?'. Values of such dictionary can be strings, or arrays of strings to form multiple values with the same key. If URL already contains a query part, it is added as is without checking for duplicates. Default: none. -
datais a data object to send. For GET method it is assumed to be a query object, ifqueryis not specified. For all other requests, it is assumed to be a payload.datais assumed to be a JSON object. Default: none. -
headersis a dictionary (a key/value hash), which is used to set request headers. Values of such dictionary can be strings, or arrays of strings to form multiple values with the same key. Default: none, but if there is noAcceptheader, it is set toapplication/json.
The next batch of properties is directly related to an underlying XHR request:
-
useris a user name as a string to be sent with the request. Default: not sent. -
passwordis a password as a string. It is used only ifuseris specified. Default:''. -
timeoutis a wait time for a request in milliseconds as a number. Default: not set. -
responseTypeis a requested response type as a string. It can be:'json','arraybuffer','blob','document','text', or''. Essentially it defines an automatic conversion of a received response inresponseproperty of XHR, which is used byio()to return a value. Default: not set. -
mimeis a string used to override a returned MIME type inContent-Typeresponse header. Default: not set.
Starting with version 1.0.5 of heya/io, it understands to recreate responseText from JSON representation. For that to work following conditions should be met:
-
responseTypeis"json". -
responseTextis ignored. In order to save some bandwidth it is advisable not to include it at all. -
responseis a valid JSON object to be transferred. -
headersare to includeContent-Typeasapplication/jsonfor consistency.
It allows to reformulate the previous example like that:
{
"options": {"url": "/abc"}, // options object
"response": {
"status": 200, // an HTTP status code
"statusText": "OK", // an HTTP status text corresponding to status code
"responseType": "json", // should be "json"
"response": [1,2,3], // a payload as an object
"headers": "Content-Type: application/json" // raw headers
}
}This extension is used mainly for debugging, because usually a debugger makes it easier to inspect an object, than its textual representation — the former can be represented in a hierarchical fashion, while the latter looks like a huge string with multiple escaped characters.
Another reason is that sometimes we already have JSON objects to send. Using this extension we can avoid an extra call to JSON.stringify().
In order to profile an I/O implementation, bundler may include optional time property, which is a number in milliseconds that takes to process a request.
This property can be added on an item level to measure how much time did it take to do an individual I/O request:
{
"options": {"url": "/abc"}, // options object
"time": 200, // in ms
"response": {
// a response object described above
}
}It can be added on a bundle level to measure the whole bundle:
{
"bundle": "bundle",
"time": 300, // in ms
"results": [
// a list of result items
]
}This reference implementation implements fully the main protocol and its optional time extension.