Using cURL to access the IzoT Server REST API

cURL is a multi-platform command-line tool for transferring data with URL syntax using various protocols, and may be used for accessing the IzoT Server REST API.

 

For further information on cURL syntax, see the curl manual page.

 

Basic Operation

In the following examples we will use the HTTP protocol. This allows you to more easily view the exchanges using a web developer browser plug-in or monitor, but this is insecure. In production use, you should always use the HTTPS protocol. We will also use the hostname localhost. In practice, you would specify the IP address or hostname of the IzoT Server.

 

To retrieve the list of top-level resources, in the default (JSON) format:

curl http://localhost/api/
{
    "datapoints": "http://localhost/api/datapoints/",
    "devices": "http://localhost/api/devices/",
    "users": "http://localhost/api/users/"
}

To retrieve the list of top-level resources, in a specific format, e.g. XML, by specifying a format suffix, a format parameter, or an Accept header:

curl http://localhost/api/.xml
curl http://localhost/api/?format=xml
curl -H "Accept: application/xml" http://localhost/api/
<?xml version="1.0" encoding="utf-8"?>
<root>
    <datapoints>http://localhost/api/datapoints/</datapoints>
    <devices>http://localhost/api/devices/</devices>
    <users>http://localhost/api/users/</users>
</root>

Add the -v option to curl to see headers sent to and received from the IzoT Server along with any failure codes.

 

Authentication

Accesing the IzoT Server's top-level resource list did not require any special permissions and so it was not necessary to authenticate with the API first. Retrieving other resources, however, requires an authenticated session.

 

Failure to (successfully) authenticate, will result in an error accompanied by an error description response:

curl -v http://localhost/api/devices/
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /api/devices/ HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost
> Accept: */*
> 
< HTTP/1.1 403 FORBIDDEN
< Date: Wed, 30 Jul 2014 00:11:56 GMT
< Content-Type: application/json
< Transfer-Encoding: chunked
< Connection: keep-alive
* Server WSGIServer/0.2 CPython/3.4.0 is not blacklisted
< Server: WSGIServer/0.2 CPython/3.4.0
< Allow: GET, POST, PUT, HEAD, OPTIONS, PATCH
< X-IzoTServer: IzoTServer/1.02.20 (zhabhqf1gc)
< Vary: Accept, Cookie
< 
* Connection #0 to host localhost left intact
{"detail": "Authentication credentials were not provided."}

When you interact with the API through a web browser, you can login, and the browser session will then provide the required authentication for the requests.

 

If you're interacting with the API programmatically you need to explicitly provide the authentication credentials on each request.

curl -u username:password http://localhost/api/devices/
        
[
    {"id": 1, "name": "cpu",    "type": "cpu",    ... }, 
    {"id": 2, "name": "memory", "type": "memory", ... }, 
    {"id": 3, "name": "disk",   "type": "disk",   ... }
]

If you specify only the username, curl will prompt you for the password.

 

This form of access control uses Basic Authentication, and should only ever be used in production over a secure (HTTPS) connection. Additionally, requests sent using Basic Authentication are slow because each request must be individually authenticated.

 

Logging In (Creating a Session)

Instead of sending credentials with every request, a session can be established with the IzoT Server REST API by first logging in, obtaining a Session Token (in the form of a cookie) and then passing the Session Token to the server in all subsequent requests. The resulting session will be valid for 2 weeks by default.

 

In order to successfully send any 'unsafe' (POST, PUT, PATCH and DELETE) requests (including the login request) to the IzoT Server REST API, you will first need to retrieve a site-specific CSRF Token (again, in the form of a cookie), and then pass this back to the server via a cookie and a custom X-CSRFToken header with all subsequent POST requests.

 

All IzoT Server REST API cookies are named with an IzoT Server Instance ID suffix. The Instance ID is listed under IzoT Server Information of the IzoT Server's Web page, and can be read from the X-IzoTServer header of all IzoT Server REST API responses (it can also be extracted from the suffix of the cookies).

 

So, to login, first retrieve the CSRF Token by making a GET request to the login page, /auth/login/, storing all cookies (including an unauthenticated session cookie) to a local file (discarding the unneeded login page HTML):

curl -s -c cookies.txt http://localhost/auth/login/ > /dev/null

The cookies.txt file will look something like this:

# Netscape HTTP Cookie File
# http://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
localhost       FALSE   /       FALSE   1438210365
    csrftoken-zhabhqf1gc    hma9slwEVUZ4nY7FGnBXYCio8c7bdza3
#HttpOnly_localhost     FALSE   /       FALSE   1407970365
    sessionid-zhabhqf1gc    zfrzppodjqrsipdism8cmslmyvg5is6z

Then, extract the Server Instance ID and CSRF Token (the two highlighted strings above) from the cookies, e.g. using awk from a bash shell:

INSTANCE=$(awk -F '[ \t\-]+' '/csrftoken/ {print $7}' cookies.txt)
CSRFTOKEN=$(awk -F '[ \t\-]+' '/csrftoken/ {print $8}' cookies.txt)

Next, POST your credentials to the login page along with your cookies and header(s):

curl -b cookies.txt -c cookies.txt -H "X-CSRFToken: $CSRFTOKEN" \
     -X POST -d "username=username&password=password" \
     http://localhost/auth/login/ -s > /dev/null

If successfully authenticated, the response will include a new Session Token and the cookie file will be updated to include the new (authenticated) session cookie. Now, just send the session cookie back with all subsequent requests:

curl -b cookies.txt http://localhost/api/devices/
[
    {"id": 1, "name": "cpu",    "type": "cpu",    ... }, 
    {"id": 2, "name": "memory", "type": "memory", ... }, 
    {"id": 3, "name": "disk",   "type": "disk",   ... }
]

Logging Out

Not using or destroying the session cookie (e.g. rm cookies.txt) is similar to being logged out, but to clean up the session on the server (ensuring that the session token can't be reused), make a GET request to the logout page:

curl -b cookies.txt http://localhost/auth/logout/ -s > /dev/null

To clear out all expired sessions on the server, you can run the following management command (you can also run this run regularly from a cron job):

$IZOT/izot/server/manage.py clearsessions

 

Reading Data

To read data, e.g. read a datapoint's value, send a GET request:

curl -b cookies.txt http://localhost/api/datapoints/1/?fields=name,value
{"name": "cpu_utilization", "value": "13.3"}

 

Writing Data

To write data, e.g. update a datapoint's notes field, send a PUT or PATCH request specifying the content type of the data (and remembering that all 'unsafe' operations also require the CSRF Token header):

curl -b cookies.txt -H "X-CSRFToken: $CSRFTOKEN" \
     -X PATCH -H "Content-Type: application/json" -d '{"notes": "off"}' \
     http://localhost/api/datapoints/1/