From, an OpenBSD-based firewall
Jump to: navigation, search

REST[1] (Representational state transfer) or RESTful APIs have become increasingly popular. Because it's not perfectly fit for all the functionality that our system provides, our primary API is SOAP.

We do however realise that there might be cases when SOAP is not an option, and therefore provide a REST proxy. Input and output is JSON encoded, and the arguments are described on the SOAP page and XLST styled WSDL file accessible as https://system/remote/


List all configuration revisions:

GET /rest/config

Commit and apply a new configuration file:

POST /rest/config
{ "message": "added vlan", "config": "interface em0..." }

View the running configuration:

GET /rest/config/head

View a specific revision:

GET /rest/config/ID

Tag a revision:

PUT /rest/config/ID/tag
{ "message": "before clustering" }

Proxy code

<hsl> if (!isset($_SERVER['PHP_AUTH_USER'])) {

       header('HTTP/1.0 401 Unauthorized');
       header('WWW-Authenticate: Basic realm="Halon REST"');

} set_exception_handler(error); $url = ''; $soap = new SoapClient($url.'/remote/?wsdl', array(

       'location' => $url.'/remote/',
       'uri' => 'urn:halon',
       'login' => $_SERVER['PHP_AUTH_USER'],
       'password' => $_SERVER['PHP_AUTH_PW']

)); $data = json_decode(file_get_contents('php://input')); if ($data === null) $data = (object)$_GET;

if (is_call('GET', array('config'))) json($soap->configRevisionLog()); if (is_call('POST', array('config'))) json($soap->configCommit($data)); if (is_call('GET', array('config', 'head'))) json($soap->configCheckout(-1)); if (is_call('GET', array('config', 'ID'), 'revision')) json($soap->configCheckout($data)); if (is_call('PUT', array('config', 'ID', 'tag'), 'revision')) json($soap->configTag($data)); if (is_call('POST', array('commit', 'ID'), 'uuid')) json($soap->configConfirm($data)); if (is_call('DELETE', array('commit', 'ID'), 'uuid')) json($soap->configCancel($data)); if (is_call('POST', array('check'))) json($soap->configCheck($data)); if (is_call('GET', array('file'))) json($soap->fileRead($data)); if (is_call('PUT', array('file'))) json($soap->fileWrite($data)); if (is_call('GET', array('interfaces'))) json($soap->getInterfaces()); if (is_call('GET', array('serial'))) json($soap->getSerial()); if (is_call('GET', array('time'))) json($soap->getTime()); if (is_call('PUT', array('time'))) json($soap->systemTime($data)); if (is_call('GET', array('uptime'))) json($soap->getUptime()); if (is_call('GET', array('graph'))) json($soap->graphList()); if (is_call('GET', array('graph', 'ID'), 'name')) binary($soap->graphFile($data)); if (is_call('GET', array('license'))) json($soap->licenseExport()); if (is_call('POST', array('license'))) json($soap->licenseInstall($data)); if (is_call('DELETE', array('license', 'ID'), 'key')) json($soap->licenseRemove($data)); if (is_call('PUT', array('power', 'off'))) json($soap->systemPowerOff()); if (is_call('PUT', array('power', 'reset'))) json($soap->systemReboot()); if (is_call('GET', array('software'))) json($soap->getVersion()); if (is_call('PUT', array('software'))) json($soap->systemUpdate($data)); if (is_call('POST', array('command'))) json($soap->commandRun($data)); if (is_call('GET', array('command', 'ID'), 'commandid')) json($soap->commandPoll($data)); if (is_call('POST', array('command', 'ID'), 'commandid')) json($soap->commandPush($data)); if (is_call('PUT', array('command', 'ID', 'signal'), 'commandid')) json($soap->commandPush($data)); if (is_call('PUT', array('command', 'ID', 'stop'), 'commandid')) json($soap->commandStop($data)); if (is_call('PUT', array('command', 'ID', 'term'), 'commandid')) json($soap->commandTermsize($data)); die('unknown call');

function is_call($method, $argv, $id = false) {

       global $data;
       $path = explode('/', $_SERVER['PATH_INFO']);
       if ($_SERVER['REQUEST_METHOD'] != $method)
               return false;
       if (count($path) != count($argv) + 1)
               return false;
       foreach($argv as $i => $a) {
               if ($a == 'ID')
                       $data->{$id} = $path[$i+1];
               else if ($path[$i+1] != $a)
                       return false;
       return true;


function json($data) {

       header('Content-type: application/json');
       echo json_encode($data);


function binary($data) {

       header('Content-type: application/octet-stream');
       echo $data->result;


function error($e) {

       header('HTTP/1.0 500 Internal Server Error');
       header('Content-type: application/json');
       echo json_encode(array('error' => $e->getMessage()));

} </hsl> The PHP code above should usually be placed within <?php tags, and accompanied with a rewrite directives such as (Apache example)

RewriteEngine On
RewriteBase /rest/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]