Edgio

Control REST APIs Common Structure

Control APIs are RESTful APIs that leverage HTTP’s well-defined and consistent message envelope. RESTful architectures are designed for resource passing by placing method information in the method, scoping information in the path, client information in the headers, and the representation of the resource in the body.
The elements of the HTTP request are:
  • Method
  • URI path and parameters
  • Header
  • Representation of resource in the body or document
The elements of the HTTP responses are:
  • Response code
  • Header
  • Representation of resource in the body or document

HTTP Requests

URI Path and Parameters

The general form of the URL for requests is:
https://host:port/${api-name}/${version}/${resource-name}/${sub-level}/${resourceId}?${params}
where:
  • host and port - define the host and port where the application lives (port is optional)
  • api-name - API name (for example, purge-api)
  • version - the API version for this feature (e.g., v1)
  • resource-name - name of the resource requested (e.g., request)
  • sub-level - optional level to further specify the requested resource
  • resourceId - resource identifier, if applicable for the method
  • params - additional parameters for pagination, search, authentication, etc.
Unless otherwise noted, arguments are case-sensitive.

API Version

The REST APIs are subject to version control. The version number of an API appears in its URI. For example, this URI structure requests version 1 of an API: https://host:port/api-name/v1/resource-names
Notes:
  • The API version number is an integer with v prefix, such as v1 or v2.
  • The API version is independent of the release number.
  • The API version may or may not change with a new release. The API version number changes only when updates to the API break the API contract, requiring changes in the code that uses the API. A change to the API does not necessarily require a change to the API version number.
  • For multiple API versions, each version will ideally support at least two API versions: the latest API version and the previous API version.

Media Type

Some REST API requests accept resources, and most REST API responses return resources. These resources can be in either JSON or XML format; the default is JSON. The media type of the request resource must be specified in the Content-Type header (application/json or application/xml). The media type of the response resource is specified in the URI (responseType=json or responseType=xml) or in the Accept header (application/json or application/xml).

Parameters

URI parameters can be for pagination, search, authentication, and/or specific parameters for an API resource.

Authentication

The Edgio REST APIs use a combination of symmetric key cryptography and Hashed Message Authentication Code (HMAC) for message authentication and user identification.
To secure all calls to the API, an HMAC digest signature is applied to each request by using the following authentication headers:
  • X-LLNW-Security-Principal – name of user performing the request. Services look up shared keys by username to authenticate a message. Since shared keys are stored on a per-user basis, to impersonate another user, an attacker would have to know both the username and the shared key for that user.
  • X-LLNW-Security-Timestamp – request time in milliseconds. Prevents replay attacks. If the timestamp is more than X seconds old (usually 300), the message expires, and an error code is returned. Note: System clock skew minimization is an important consideration for message expiration.
  • X-LLNW-Security-Token – MAC hash-generated with the user’s shared key. It is calculated based on data that is sent to the server. This token is generated twice: once by the client and once by the server to compare with the one passed by the client. If the token provided by the client matches the token generated by the server, the message is authentic. Shared key is a large unique key created for use with the “HmacSHA256” MAC algorithm. Control maintains a unique and enciphered shared key for every user in the system. It is stored in HEX format and should be decoded to ASCII before usage (see code samples below).  Users may access or regenerate this key at any time by using tools in Control under My Settings > Edit My Profile.
    • X-LLNW-Security-Token is formed by applying a MAC digest for the “data string” (for example, REQUEST_METHOD + URL + QUERY_STRING [if present] + TIMESTAMP + REQUEST_BODY (if present)).

Java Sample Code for HMAC Generation

java
1import java.io.IOException;
2import java.io.UnsupportedEncodingException;
3import java.security.InvalidKeyException;
4import java.security.NoSuchAlgorithmException;
5import javax.crypto.Mac;
6import javax.crypto.spec.SecretKeySpec;
7import org.apache.commons.codec.DecoderException;
8import org.apache.commons.codec.binary.Hex;
9public class HMACGenerationExample {
10 private static String HMAC_ALGORITHM = "HmacSHA256";
11 public static void main(String[] args) throws IOException,
12 InterruptedException, InvalidKeyException, NoSuchAlgorithmException,
13 DecoderException {
14 String sharedKey = "your_key";
15 //sharedKey is what you see in Control on Edit My Profile page
16 String url = "<api base url>";
17 /* base url example: "https://control.llnw.com/
18 traffic-reporting-api/v2" */
19 String queryString = "<query string parameters>";
20 /*queryString example: "shortname=bulkget&service=http&
21 reportDuration=day&startDate=2012-01-01" */
22 String postData = "{param1: 123, param2: 456}";
23 byte[] rawHmac = generateMac(sharedKey, "GET", url, queryString,
24 postData);
25 String hmac = new String(Hex.encodeHex(rawHmac));
26 System.out.println(hmac);
27 }
28 private static byte[] generateMac(String sharedKey, String httpMethod,
29 String url, String queryString,
30 String postBody)
31 throws NoSuchAlgorithmException, InvalidKeyException,
32 IllegalStateException, UnsupportedEncodingException,
33 DecoderException {
34 byte[] decodedSharedKey = Hex.decodeHex(sharedKey.toCharArray());
35 long timestamp = System.currentTimeMillis();
36 String dataString;
37 if (queryString == null) {
38 dataString = httpMethod.toUpperCase() + url + timestamp;
39 } else {
40 dataString = httpMethod.toUpperCase() + url + queryString +
41 timestamp;
42 }
43
44 if (postBody != null) {
45 dataString = dataString + postBody;
46 }
47 SecretKeySpec keySpec = new SecretKeySpec(decodedSharedKey,
48 HMAC_ALGORITHM);
49 Mac mac = Mac.getInstance(HMAC_ALGORITHM);
50 mac.reset();
51 mac.init(keySpec);
52 return mac.doFinal(dataString.getBytes("UTF-8"));
53 }
54}

Python Sample Code for HMAC Generation

python
1import hashlib
2import hmac
3import time
4try: import simplejson as json
5except ImportError: import json
6class HMACSample:
7 def generateSecurityToken(self, url, httpMethod, apiKey, queryParameters=None, postData=None):
8 timestamp = str(int(round(time.time()*1000)))
9 datastring = httpMethod + url
10 if queryParameters != None : datastring += queryParameters
11 datastring += timestamp
12 if postData != None : datastring += postData
13 token = hmac.new(apiKey.decode('hex'), msg=datastring, digestmod=hashlib.sha256).hexdigest()
14 return token
15if __name__ == '__main__':
16 apiEndpoint = "<api base url>"
17 #example: "https://control.llnw.com/traffic-reporting-api/v2"
18
19 #what you see in Control on Edit My Profile page#
20 apiKey = "your_key";
21
22 queryParameters = "<query string parameters>"
23 #example: "shortname=bulkget&service=http&reportDuration=day&startDate=2012-01-01"
24 postData = "{param1: 123, param2: 456}"
25 tool = HMACSample()
26 hmac = tool.generateSecurityToken(url=apiEndpoint, httpMethod="GET", queryParameters=queryParameters, postData=postData, apiKey=apiKey)
27 print json.dumps(hmac, indent=4)

Request Header

The Accept HTTP Header can specify the response format. The default is JSON.
Accept=application/json
The Content-Type HTTP Header can specify the format of the request body. This header is required for all resources that require a request body.
Content-Type=json
The HTTP X-LLNW-Security-Token, X-LLNW-Security-Principal, X-LLNW-Security-Timestamp headers form the authentication envelope.
X-LLNW-Security-Token=<mac>
X-LLNW-Security-Principal=<username>
X-LLNW-Security-Timestamp=<now in milliseconds>

Representation of Resource in the Body or Document

Some APIs expect a payload of information in JSON format in the request body for PUT or POST methods. This payload is known as the body or document of the request and is a representation of the resource for the API. The format must specified with the Content-Type header.

HTTPS Responses

A response header, returned for each API request, contains:
  • one of the HTTP Response Status Codes
  • the returned media type in the Content-Type header (for example, application/json;charset=UTF-8)
The response body, returned for each API request, contains either:
  • a status entity or
  • a response entity (representation of the resource)
The format of the response body is determined by the responseType parameter or Accept HTTP Header in the request.

HTTP Response Status Codes

HTTP Status CodeNameDescription
5xxServer-Side ErrorAny server-side error
200OKRequest was processed as expected.
201CreatedRequest created an entity.
202AcceptedRequest was processed as expected.
304Not ModifiedThe requested resource has not been modified, and the client’s cached representation is still valid.
400Bad RequestThe request could not be understood due to bad syntax.
401UnauthorizedClient is not authenticated or does not have sufficient permission to perform this request.

Similar to 403 Forbidden but specifically for use when authentication is possible but has failed or has not yet been provided.
403ForbiddenThe request was a legal request, but the server is refusing to respond to it.

Unlike a 401 Unauthorized response, authenticating will make no difference.
404Not foundThe requested resource could not be found at this location (URI), but may be available again in the future. Subsequent requests by the client are permissible.