macchina.io REMOTE REST API

Overview

The macchina.io REMOTE server provides a REST API for programmatically querying and modifying device meta information. Using the API you can get a list of devices, search for a device, get and modify device properties, create and delete devices.

Endpoint

The HTTP or HTTPS endpoint for all API requests is remote.macchina.io. We highly recommend using HTTPS, especially if sensitive data like usernames and passwords are transmitted. This is especially true if HTTP Basic Authentication is used.

Authentication

The API supports three authentication mechanisms. The first is HTTP Basic Authentication (over HTTPS), the second one is session-based authentication, and the third one is bearer token-based authentication.

HTTP Basic Authentication

For HTTP Basic authentication, the username and password must be supplied in the Authorization header with every HTTP request.

Note: all following examples use username "user" and password "s3cr3t".

Following is an example for a request using Basic Authentication:

GET /my-devices/api/devices HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close

Session-Based Authentication

The second authentication mechanism is session-based authentication. This uses a session cookie, which must be passed with every request, along with a XSRF (CSRF) token to prevent cross-site request forgery attacks. To obtain valid session and XSRF token cookies, a Login request must be sent to theserver. This is a POST request to the server root ("/"), with the username and password supplied as form-encoded parameters in the request body.

POST / HTTP/1.1
Host: remote.macchina.io
Connection: Close
Content-Length: 42
Content-Type: application/x-www-form-urlencoded

action=login&username=user&password=s3cr3t

The following parameters must be given:

  • action: This must always have the value login.
  • username: The name of the user.
  • password: The user's password.

Instead of a username and password, a JSON Web Token (JWT) can be used for authenticating the user. The JWT is passed in a parameter named jwt. See below for how to obtain the token from the server.

Additionally, the following optional parameters can be passed:

  • onsuccess: The URI of a page to redirect to if the login was successful. If this is given and authentication was successful, the response will have a 303 See Other status with a Location header containing the URI given here.
  • onfailure: Similar to onsuccess, the URI given here will be used if authentication failed.

If onsuccess and onfailure are not given, the response status will be 200 OK if authentication succeeded, or 401 Unauthorized if authentication failed.

If onsuccess or onfailure contain URLs pointing to external web servers, these URLs must be whitelisted in the macchina.io REMOTE server configuration file.

If authentication was successful, the response will include Set-Cookie headers containing the session cookie (osp.web.session.my-devices) and XSRF token (XSRF-TOKEN). This session cookie and XSRF token must be passed in with all API requests. The XSRF token must be passed in the X-XSRF-TOKEN request header.

HTTP/1.1 200 OK
Connection: Close
Content-Length: 0
Date: Thu, 01 Mar 2012 10:35:30 GMT
Set-Cookie: osp.web.session.my-devices=a75fece1fc6d045049d7e1c832ddb1550c002e67;
    domain=.remote.macchina.io;
    path=/;
    HttpOnly;
    expires=Thu, 01 Mar 2012 12:35:30 GMT
Set-Cookie: XSRF-TOKEN=6c7b5b839425b23359d38a8082a73858b68c478e;
    path=/;
    expires=Thu, 01 Mar 2012 12:35:30 GMT

Here is an example for using the session cookie and XSRF token in a REST request:

GET /my-devices/api/devices HTTP/1.1
Host: remote.macchina.io
Cookie: osp.web.session.my-devices=a75fece1fc6d045049d7e1c832ddb1550c002e67
X-XSRF-TOKEN: 6c7b5b839425b23359d38a8082a73858b68c478e
Connection: Close

Bearer Token-Based Authentication

In order to use bearer token-based authentication, a bearer token must be obtained first. This token must then be passed along with every request in the HTTP Authorization header using the Bearer scheme.

Obtaining a Bearer Token

To obtain the token, send a request to the /my-devices/api/token endpoint, passing the following parameters as form data:

  • username: The name of the user the token should be issued to.
  • password: The password used to authenticate the user.
  • application: The name of the application the token should be issued to.
  • secret: The application secret (optional), used for reserved application names.

Example:

POST /my-devices/api/token HTTP/1.1
Host: remote.macchina.io
Content-Type: application/x-www-form-urlencoded
Content-Length: 57

username=user&password=s3cr3t&application=DemoApplication

If successful, the server will respond with a JSON containing the token in JSON Web Token (JWT) format, as well as the validity period of the token.

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 297

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEZW1vQXBwbGljYXRpb24iLCJleHAiOjE1NjczMjE1NTAuOTA4MjIyLCJpYXQiOjE1NjcyMzUxNTAuOTA4MDk2LCJqdGkiOiJkMzdjYjRlYS1lYmZkLTQyM2QtYWNjYi1kY2RjNWNkMTdiMmIiLCJzdWIiOiJ1c2VyIn0.9BWgKeW9-6kd0vqNR6GVz2XUG5bOYdPHuYlHLCGCn70",
  "expires": 1567321550
}

The expiry time is given in seconds since midnight, January 1st 1970, UTC.

Passing the Bearer Token

The received bearer token must be passed in the Authorization header, using the Bearer scheme.
Example:

GET /my-devices/api/users HTTP/1.1
Host: remote.macchina.io
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEZW1vQXBwbGljYXRpb24iLCJleHAiOjE1NjczMjE1NTAuOTA4MjIyLCJpYXQiOjE1NjcyMzUxNTAuOTA4MDk2LCJqdGkiOiJkMzdjYjRlYS1lYmZkLTQyM2QtYWNjYi1kY2RjNWNkMTdiMmIiLCJzdWIiOiJ1c2VyIn0.9BWgKeW9-6kd0vqNR6GVz2XUG5bOYdPHuYlHLCGCn70

Authentication with Device Credentials

Some API requests, specifically getting and setting device properties, can also be made using device credentials. Device UUID and device password must be supplied using HTTP Basic authentication. A device password must have been set using the "password" device property. The special device UUID "self" must be used in the resource path instead of the actual device UUID (which is passed in the Authorization header).

Accessing Device Web Servers

The device web server of any device that is connected to the reflector server can be reached under the address <id>.remote.macchina.io, where <id> is the UUID identifying the device.

To access the device, a valid session cookie is required. Alternatively, HTTP Basic Authentication can be used to provide authentication info. However, as to not conflict with possible authentication required by the device itself, the authentication information is not passed via the Authorization header, but via the X-PTTH-Authorization header instead.

Example:

GET / HTTP/1.1
Host: a2359c27-cb1f-4692-8490-22d412ac87ba.remote.macchina.io
X-PTTH-Authorization: Basic dXNlcjpzM2NyM3Q=

This is a very useful feature for programmatically "pushing" data to devices, using a POST or PUT request to the device's web server.

The X-PTTH-Authorization header can also be used for bearer token-based authentication.

Example:

GET / HTTP/1.1
Host: a2359c27-cb1f-4692-8490-22d412ac87ba.remote.macchina.io
X-PTTH-Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEZW1vQXBwbGljYXRpb24iLCJleHAiOjE1NjczMjE1NTAuOTA4MjIyLCJpYXQiOjE1NjcyMzUxNTAuOTA4MDk2LCJqdGkiOiJkMzdjYjRlYS1lYmZkLTQyM2QtYWNjYi1kY2RjNWNkMTdiMmIiLCJzdWIiOiJ1c2VyIn0.9BWgKeW9-6kd0vqNR6GVz2XUG5bOYdPHuYlHLCGCn70

Browsing Devices

For browsing all available devices, send a GET request to /my-devices/api/devices. Optionally, parameters can be supplied to filter or limit the result.

To get a list of all devices, that are online, send the following request:

GET /my-devices/api/devices HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close

The response will contain a JSON array of objects holding device properties (id, domain, name, online, etc.) in the body:

HTTP/1.1 200 OK
Cache-Control: no-cache
Connection: Close
Content-Type: application/json
Date: Thu, 01 Mar 2012 11:25:31 GMT
Transfer-Encoding: chunked

[
    {
        "name": "Network Camera",
        "geolocation": "46.528760, 14.099177",
        "port": "0",
        "lastConnect": "2012-03-01T11:25:02Z",
        "id": "0a72da53-9de5-44c8-9adf-0090e80e20a7",
        "host": "80.122.195.86",
        "online": true,
        "domain": "e3efbb09-f384-4c00-8e7a-e18b8e93c362",
        "description": "Network camera at office"
    },
    {
        "name": "Web HMI Demo",
        "geolocation": " 46.528760, 14.099177",
        "port": "0",
        "lastConnect": "2012-03-01T11:25:26Z",
        "id": "33a9c5a3-81d8-4d3a-8068-1c910b3c61f6",
        "host": "188.22.62.220",
        "online": true,
        "domain": "e3efbb09-f384-4c00-8e7a-e18b8e93c362",
        "description": "Industrial HMI built with web technologies",
        "hardware": "Digi ConnectCore 9C"
    },
    {
        "name": "iWeatherStation",
        "geolocation": "46.528760, 14.099177",
        "port": "0",
        "lastConnect": "2012-03-01T11:25:15Z",
        "id": "a2359c27-cb1f-4692-8490-22d412ac87ba",
        "host": "80.122.195.86",
        "online": true,
        "domain": "e3efbb09-f384-4c00-8e7a-e18b8e93c362",
        "description": "Internet-based weather station device",
        "hardware": "SSV DNP/9200"
    }
]

Note: in order to improve readability, the chunk sizes have been stripped from the responses shown in this document.

The following parameters can be added:

  • query: Specify a whitespace-separated list of keywords to only return devices matching these keywords. If any of the keywords are found in the name, description or tags properties of the device, then the device will be included in the result.
  • sort: Specify a sort criteria to order the result by. Valid values are domain, id, host, lastConnect, name, online and protocol.
  • dir: Specify sort direction. Valid values are asc (default) and desc.
  • fromIndex: A zero-based index of the first desired result. This is used for paging output, along with maxResults.
  • maxResults: Maximum number of results for paged output. Usually used together with fromIndex.
  • status: Only include devices with the given online status. Valid values are online, offline and all.
  • domain: Only include devices with the given domain. The domain UUID must be given as value.

Example: Browse for all devices containing the keyword "camera" in their name, description or tags and order by last connect time:

GET /my-devices/api/devices?query=camera&sort=lastConnect HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close

Server Response:

HTTP/1.1 200 OK
Cache-Control: no-cache
Connection: Close
Content-Type: application/json
Date: Thu, 01 Mar 2012 11:19:21 GMT
Transfer-Encoding: chunked

[
    {
        "name": "Network Camera",
        "geolocation": "46.528760, 14.099177",
        "port": "0",
        "lastConnect": "2012-03-01T11:19:07Z",
        "id": "0a72da53-9de5-44c8-9adf-0090e80e20a7",
        "host": "80.122.195.86",
        "online": true,
        "domain": "e3efbb09-f384-4c00-8e7a-e18b8e93c362",
        "description": "Network camera at office"
    }
]

Example: paged results:

GET /my-devices/api/devices?firstIndex=1&maxResults=10 HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close

Getting Properties of a Specific Device

To return all device properties for a device identified by its UUID, issue a GET request to /my-devices/api/device/<id>, where <id> is replaced with the device UUID.

Example:

GET /my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7 HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close

Server Response:

HTTP/1.1 200 OK
Cache-Control: no-cache
Connection: Close
Content-Type: application/json
Date: Thu, 01 Mar 2012 11:36:32 GMT
Transfer-Encoding: chunked

{
    "name": "Network Camera",
    "geolocation": "46.528760, 14.099177",
    "port": "0",
    "lastConnect": "2012-03-01T11:35:59Z",
    "id": "0a72da53-9de5-44c8-9adf-0090e80e20a7",
    "host": "80.122.195.86",
    "online": true,
    "domain": "e3efbb09-f384-4c00-8e7a-e18b8e93c362",
    "description": "Network camera at office"
}

It is also possible to only return a specific property. To do this, the name of the property must be added to the request URI:

GET /my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7/name HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close

Server Response:

HTTP/1.1 200 OK
Cache-Control: no-cache
Connection: Close
Content-Type: application/json
Date: Thu, 01 Mar 2012 11:36:32 GMT
Transfer-Encoding: chunked

{
    "name": "Network Camera"
}

A device can query its own properties if a device password has been set using the "password" device property. The device UUID and password are used to authenticate the request. Instead of the device UUID, the special keyword "self" is used in the resource path.

GET /my-devices/api/device/self/name HTTP/1.1
Host: remote.macchina.io
Authorization: Basic MGE3MmRhNTMtOWRlNS00NGM4LTlhZGYtMDA5MGU4MGUyMGE3OnMzY3IzdA==
Connection: Close

Server Response:

HTTP/1.1 200 OK
Cache-Control: no-cache
Connection: Close
Content-Type: application/json
Date: Thu, 01 Mar 2012 11:36:32 GMT
Transfer-Encoding: chunked

{
    "name": "Network Camera"
}

Setting Properties of a Specific Device

The properties of a device can be modified, and new properties can be added. This is done with a PUT or PATCH request to /my-devices/api/device/<id>, where <id> is replaced with the device UUID.

The new property values are given through a JSON document in the request body.

PUT and PATCH are equivalent, although PATCH is semantically more appropriate.

Example:

PUT /my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7 HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close
Content-Type: application/json
Content-Length: 38

{
    "name": "Network Camera"
}

Server Response:

HTTP/1.1 200 OK
Connection: Close
Content-Length: 0
Date: Thu, 01 Mar 2012 11:38:24 GMT

Note: System properties (id, domain, online, lastConnect, host and port) cannot be modified with PUT or PATCH. For updating the domain property, see Creating or Updating a Device.

A device can modify its own properties if a device password has been set using the "password" device property. The device UUID and password are used to authenticate the request. Instead of the device UUID, the special keyword "self" is used in the resource path.

Example:

PUT /my-devices/api/device/self HTTP/1.1
Host: remote.macchina.io
Authorization: Basic MGE3MmRhNTMtOWRlNS00NGM4LTlhZGYtMDA5MGU4MGUyMGE3OnMzY3IzdA==
Connection: Close
Content-Type: application/json
Content-Length: 38

{
    "name": "Network Camera"
}

Server Response:

HTTP/1.1 200 OK
Connection: Close
Content-Length: 0
Date: Thu, 01 Mar 2012 11:38:24 GMT

Deleting a Device Property

A device property can be deleted with a DELETE request to /my-devices/api/device/<id>/<prop>, where <id> is replaced with the device UUID and <prop> is replaced with the property name.

Example:

DELETE /my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7/tags HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close
Content-Length: 0

Server Response:

HTTP/1.1 200 OK
Connection: Close
Content-Length: 0
Date: Thu, 01 Mar 2012 11:44:32 GMT

Deleting a Device

A device can be deleted with a DELETE request to /my-devices/api/device/<id>, where <id> is replaced with the device UUID.

Deleting a device is normally only allowed if the device is offline (disconnected). However, by adding the X-PTTH-Force: disconnect header to the request, the device will be disconnected before being deleted.

Example:

DELETE /my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7 HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close
Content-Length: 0

Server Response:

HTTP/1.1 200 OK
Connection: Close
Content-Length: 0
Date: Thu, 01 Mar 2012 11:44:32 GMT

Creating a Device

A device can be created with a POST request to /my-devices/api/device/<id>, where <id> is replaced with the device ID of the new device.

The new device properties must be passed as JSON object in the request body. The properties must at least include domain and name. The id property must not be included. The id and online properties will be set automatically. The domain UUID must be one the user account has been authorized to access.

Example:

POST /my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7 HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close
Content-Length: 195

{
    "name": "Network Camera",
    "geolocation": "46.528760, 14.099177",
    "domain": "e3efbb09-f384-4c00-8e7a-e18b8e93c362",
    "description": "Network camera at office"
}

Server Response:

HTTP/1.1 200 OK
Connection: Close
Content-Length: 0
Date: Thu, 01 Mar 2012 11:44:32 GMT

Creating or Updating a Device

POST can also be used to update an existing device's properties. For this to work, a X-PTTH-If-Exists: update header must be included in the request.

If this header is included, and the device with the given ID already exists, it's properties will be updated. If the device does not exist, it will be created.

This is also the only way the domain property of an existing device can be changed.

It is furthermore possible to add a X-PTTH-If-Exists: reset header to the request. In this case, if the device already exists, it will be deleted first, then immediately re-created with the new properties.

Note: Deleting a device is normally only allowed if the device is offline (disconnected). However, by adding the X-PTTH-Force: disconnect header to the request, the device will be disconnected before being deleted and subsequently recreated.

Example:

POST /my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7 HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
Connection: Close
Content-Length: 195
X-PTTH-If-Exists: update

{
    "name": "Network Camera",
    "geolocation": "46.528760, 14.099177",
    "domain": "e3efbb09-f384-4c00-8e7a-e18b8e93c362",
    "description": "Network camera at office"
}

Server Response:

HTTP/1.1 200 OK
Connection: Close
Content-Length: 0
Date: Thu, 01 Mar 2012 11:44:32 GMT

HTTP Method Override (Firewall)

If your firewall does not allow HTTP PUT or HTTP DELETE requests, you can send a POST request and add the X-HTTP-Method-Override header to specify the actual method to use. Please note that method names are case sensitive.

Example:

POST /my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7 HTTP/1.1
Host: remote.macchina.io
Authorization: Basic dXNlcjpzM2NyM3Q=
X-HTTP-Method-Override: DELETE
Connection: Close
Content-Length: 0

Server Response:

HTTP/1.1 200 OK
Connection: Close
Content-Length: 0
Date: Thu, 01 Mar 2012 11:44:32 GMT

Cross-Origin Resource Sharing (CORS)

The API supports CORS and thus allows you to invoke the API from browser-based applications served from another domain. In the standard setup, CORS is allowed for all domains, but this can be changed by the server administrator to a specific domain, if required.

Error Handling

The following conventions are used by the API for reporting errors:

  • A successful action will always result in a 200 OK response.
  • If a device or property does not exist, a 404 Not Found response is returned.
  • An attempt to create a device that already exists results in a 409 Conflict response.
  • If no authentication information or bad credentials are provided, a 401 Unauthorized response is returned.
  • An incorrect HTTP method results in a 405 Method Not Allowed response.
  • If the URI is malformed, a 400 Bad Request response is returned.
  • If the server encounters an error during processing the request, a 500 Internal Server Error response is returned.

cURL Examples

The well-known cURL utility can be used to test the API.

Example 1: Get a list of all devices:

curl -uuser:s3cr3t https://remote.macchina.io/my-devices/api/devices?status=all

Example 2: Get the properties of a specific device

curl -uuser:s3cr3t \
  https://remote.macchina.io/my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7

Example 3: Set a device property:

curl -uuser:s3cr3t --request PUT \
  --data '{ "name": "My Network Camera" }' \
  --header 'Content-Type: application/json' \
  https://remote.macchina.io/my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7

Example 4: Creating a device:

curl -uuser:s3cr3t --request POST \
  --data '{ "name": "My Network Camera", "domain": "e3efbb09-f384-4c00-8e7a-e18b8e93c362"}' \
  --header 'Content-Type: application/json' \
  https://remote.macchina.io/my-devices/api/device/0a72da53-9de5-44c8-9bc3-019dee2f20a8

jQuery Examples

Example 1: Get and display a list of devices

<DOCTYPE html>
<html>
<head>
<title>remote.macchina.io API Example</title>
<script src="//code.jquery.com/jquery-3.4.1.min.js"></script>
</head>
<body>
<h1>remote.macchina.io API Example</h1>
<div id="result"></div>
<script>
$.ajax({
    url : '//remote.macchina.io/my-devices/api/devices',
    type: 'GET',
    xhrFields: {
        withCredentials: true
    },
    crossDomain: true,
    success: function(data, textStatus, jqXHR)
        {
            var result = "<table><tr><th>ID</th><th>Name</th></tr>";
            for (var i = 0; i < data.length; i++)
            {
                var device = data[i];
                result = result + "<tr>"
                       + "<td>" + device.id + "</td>"
                       + "<td>" + device.name + "</td>"
                       + "</tr>"
            }
            result = result + "</table>";
            $('#result').html(result);
        },
    error: function (jqXHR, textStatus, errorThrown)
        {
             $('#result').text(textStatus + ": " + errorThrown);
        }
});
</script>
</body>
</html>

Example 2: Get and display the properties of a device

<DOCTYPE html>
<html>
<head>
<title>remote.macchina.io API Example</title>
<script src="//code.jquery.com/jquery-3.4.1.min.js"></script>
</head>
<body>
<h1>remote.macchina.io API Example</h1>
<div id="result"></div>
<script>
$.ajax({
    url : '//remote.macchina.io/my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7',
    type: 'GET',
    xhrFields: {
        withCredentials: true
    },
    crossDomain: true,
    success: function(data, textStatus, jqXHR)
        {
            var result = "<table><tr><th>Name</th><th>Value</th></tr>";
            for (prop in data)
            {
                result = result + "<tr>"
                       + "<td>" + prop + "</td>"
                       + "<td>" + data[prop] + "</td>"
                       + "</tr>"
            }
            result = result + "</table>";
            $('#result').html(result);
        },
    error: function (jqXHR, textStatus, errorThrown)
        {
             $('#result').text(textStatus + ": " + errorThrown);
        }
});
</script>
</body>
</html>

Example 3: Setting properties of a device

<DOCTYPE html>
<html>
<head>
<title>remote.macchina.io API Example</title>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
</head>
<body>
<h1>remote.macchina.io API Example</h1>
<div id="result"></div>
<script>
$.ajax({
    url : 'https://remote.macchina.io/my-devices/api/device/0a72da53-9de5-44c8-9adf-0090e80e20a7',
    type: 'PUT',
    contentType: 'application/json',
    data: JSON.stringify(
        {
            name: 'My Network Camera',
            description: 'This is a network camera'
        }),
    username: 'user',
    password: 's3cr3t',
    xhrFields: {
        withCredentials: true
    },
    success: function(data, textStatus, jqXHR)
        {
            $('#result').text("Success!");
        },
    error: function (jqXHR, textStatus, errorThrown)
        {
             $('#result').text(textStatus + ": " + errorThrown);
        }
});
</script>
</body>
</html>

HTTP Proxy

The reflector server can act as a HTTP proxy supporting TCP connection tunneling via HTTP CONNECT requests. Any network client supporting connections through a HTTP proxy can open a connection to a device connected to the reflector server. Note that only the CONNECT method is supported. Proxying normal HTTP requests (GET, POST, etc.) is not supported.

To open a tunnel connection, send a HTTP CONNECT request to the reflector server and supply the username and password via the Proxy-Authorization header. The following example opens a connection for tunneling SSH:

CONNECT 0a72da53-9de5-44c8-9adf-0090e80e20a7.my-devices:22 HTTP/1.1
Host: 0a72da53-9de5-44c8-9adf-0090e80e20a7.my-devices:22
Proxy-Authorization: Basic dXNlcjpzM2NyM3Q=

One important drawback of this approach is that your credentials are transmitted in clear-text unless you use HTTPS for the CONNECT request. Unfortunately, most clients do not support HTTPS connections to the proxy server.