2. The HTTPS request and response structure¶
An AlpineBits® compliant server exposes a single HTTPS URL. Clients send POST requests to that URL.
The POST request must transmit the access credentials using basic access authentication.
The HTTPS header of the POST request must contain an X-AlpineBits-ClientProtocolVersion field. The value of this field is the protocol version supported by the client (see the first column of the changelog table). A server that does not receive the field will simply conclude that the client speaks a protocol version preceding the version when this field was introduced (2013-04).
The HTTPS header of the POST request may contain an X-AlpineBits-ClientID field. The value of this field is an arbitrary string which a server implementer might want to use to identify the client software version or installation ID.
The POST request must follow the multipart/form-data encoding scheme, as commonly used in the context of HTML forms for file uploads.
The POST request may be compressed using the gzip algorithm, in which case the HTTP request header Content-Encoding must be present and have "gzip" as a value. A POST request compressed with gzip must be compressed by the client in its entirety (i.e. the whole message must be compressed, not the single parts of the multipart/form-data content). It is the responsibility of the client to check whether the server supports content compression, this is done by checking the value of the HTTP response header X-AlpineBits-Server-Accept-Encoding which is set to "gzip" by servers which support this feature. The so called "Handshaking" actions must not be compressed.
The POST requests must have at least one parameter named action
. Depending on the value of action
, one additional parameter named request
might be required.
A exemplary handshake on command line using cURL with file samples/Handshake-OTA_PingRQ.xml
would look as follows.
curl --trace-ascii - -H "X-AlpineBits-ClientProtocolVersion: 2022-10" --user chris:secret -F "action=OTA_Ping:Handshaking" -F "request=<Handshake-OTA_PingRQ.xml" http://development.alpinebits.org/server-2022-10/ |
Following is the capture of the example POST from the command above. The first value of action
is the string action_OTA_Ping
, indicating the client wishes to perform the handshake, and the rest of the action listed in samples/Handshake-OTA_PingRQ.xml
. The value of request
is an XML document (not fully shown).
POST /server-2022-10/ HTTP/1.1 Host: development.alpinebits.org Authorization: Basic Y2hyaXM6c2VjcmV0 User-Agent: curl/7.64.0 Accept: / X-AlpineBits-ClientProtocolVersion: 2022-10 Content-Length: 1472 Content-Type: multipart/form-data; boundary=cd287e7912d06e8f Expect: 100-continue --cd287e7912d06e8f Content-Disposition: form-data; name="action" OTA_Ping:Handshaking --cd287e7912d06e8f Content-Disposition: form-data; name="request" Content-Type: application/xml [here is the content of the file Handshake-OTA_PingRQ.xml] --cd287e7912d06e8f-- |
Note the Authorization
field, with the username/password string (chris:secret
) encoded in base64 (Y2hyaXM6c2VjcmV0
) as defined by the basic access authentication standard 1.
Also note the X-AlpineBits-ClientProtocolVersion
and X-AlpineBits-ClientID
fields and the multipart content with the values of parameters action
and request
.
As a result of the POST request, the server answers with a response. Of course, the content of the response depends on the POSTed parameters, in particular the value of action
. AlpineBits® currently identifies two kinds of actions: the so-called handshaking actions explained in section 3 and the actual data exchange actions explained in section 4.
HTTP/1.1 200 OK Date: Thu, 21 Oct 2021 15:16:42 GMT Server: Apache X-Powered-By: Express Access-Control-Allow-Origin: * Content-Type: application/xml; charset=utf-8 Content-Length: 1653 ETag: W/"675-SunhP4r+79pVYE64e5ahe7LFpDs" Vary: Accept-Encoding X-AlpineBits-Server-Accept-Encoding: gzip [here is the response, that is identical to Handshake-OTA_PingRS.xml in the samples] |
The expected status code of the response is 200 (Ok), indicating that the server could authenticate the user (with or without being able to actually process any action).
In case of authentication failure (either an invalid or missing username/password or a value of X-AlpineBits-ClientID that is not acceptable to the server) the status code is 401 (Authorization Required) and the content is ERROR
, followed by a colon (:
) and an error message indicating the reason for the failure, such as no username/password was provided or the password expired, etc. Regarding the X-AlpineBits-ClientID
, a server chooses to require the ID or to ignore the ID. If the server chooses to ignore the ID, it must do so silently, i.e. it must not return a 401 status because of the presence of the ID.
In case of an internal server problem the status code is 500 (Internal Server Error).
A server that has not announced support for requests compressed with gzip may return the status code 501 (not implemented) in case it receives such requests.
An AlpineBits® client must be able to handle these status codes. It should retry a request that has failed (error code 500 or timeout) and only escalate the failure after 2 retries with an appropriate delay.
2.1. Implementation tips and best practice¶
-
For maximum compatibility across different implementations AlpineBits®, implementers are asked to handle POST requests using a supporting API in their language of choice. See appendix B for more resources.
-
All POSTs to an AlpineBits® server are sent to a single URL. However, a server implementer might make more than one URL available for independent servers, such as servers with support for different versions:
-
https://server.example.com/alpinebits/2011-11
-
https://server.example.com/alpinebits/2012-05b
-
etc…
-
-
Gzip compression can make a request smaller by a factor of ten, therefore it was introduced in AlpineBits® even though its usage in POST requests isn’t very common (as opposed to responses where its use is widespread). According to the various RFCs, compressing the requests is not forbidden, but there are no implementation recommendations. It was decided to use an approach major web servers were already supporting at the time of this writing.
-
When negotiating an AlpineBits® version, clients and servers should behave in the following way (this works starting from 2013-04):
-
Client: the client queries the server version, sending a header with the highest version it supports.
-
Server: if the server supports this same version, it answers with this version and the negotiation terminates successfully; otherwise the server answers with the highest version it supports.
-
Client: if the client recognizes the server version, it starts using the server version and the negotiation terminates successfully; otherwise no communication is possible, since the two parties don’t share a common version.
-