Javascript API Sample
This is a complete script demonstrating interaction with the main Web API calls to scrambls.
/**
* apiKey: the UUID doled out by Wave
*/
var apiKey = "put API key in here";
/**
* constants defined by the HTTP API
*/
var httpHdrAuth = "x-xloak-authtoken";
var httpHdrKey = "x-xloak-k";
var httpHdrClient = "x-xloak-cli";
/**
* hpBase is the "host/protocol" base URL that is common to all APIs
*/
var hpBase = "https://scrambls.com";
/**
* "api" just lists the HTTP APIs available to clients in a convenient object.
*/
var api = {uAccount: hpBase + "/upi/account",
uAuth: hpBase + "/upi/auth",
aUserPS: hpBase + "/api/userps",
aXContent: hpBase + "/api/xcontent"
};
/**
* For running in a browser window, just make the debug output bring up a dialog
*/
function DEBUG(s) {
window.alert(s);
}
/**
* xhrCall is a generic function to make a call to the server and invoke one of
* two functions once the returned data is received.
*
* Parameters:
* api: full URL; if non-POST, then must include params; pull from "api" object
* data: if defined, then API call is assumed to be POST operation; object; JSON object
* at: a valid auth token
* ok: function to call on 200 code; sig is function(parsedJSON)
* fail: function to call on non-200 code; sig is function(code)
* method: required if not GET or POST
*/
function xhrCall(api, data, ata, ok, fail, method) {
var req = new XMLHttpRequest();
var type;
// if we're sending data, then declare it to be of type application/json
// and make the method POST, unless overridden by caller
if (data) {
data = JSON.stringify(data);
type = "application/json";
if (!method)
method = "POST";
}
// default to HTTP GET method
if (!method)
method = "GET";
req.open(method, api, true); // "true" -> asynchronous call
// all API calls require a valid API key
req.setRequestHeader(httpHdrKey, apiKey);
// authenticated API calls require an auth token, so put it in the HTTP header area
if (ata) {
req.setRequestHeader(httpHdrAuth, ata);
}
// API calls that transmit data require the Content-Type header
if (type) {
req.setRequestHeader("Content-type", type);
}
// set up for asynchronous callback:
req.onreadystatechange = function (evt) {
if (req.readyState == 4) {
if (req.status == 200) {
var resp = JSON.parse(req.responseText); // format: {status:ok, info:{blah:blah, ...}}
// DEBUG(api + " got back SC=200: " + req.responseText);
if (ok)
ok(resp);
}
else {
var resp;
// DEBUG(api + " got back SC=" + req.status + ", resp = " + req.responseText + ", Content-Type header = " + req.getResponseHeader("Content-Type"));
if (req.responseText) {
resp = JSON.parse(req.responseText); // format: {blah:blah, ...}
}
if (fail) {
fail(req.status, resp);
}
}
}
}
// actually make the API call
req.send(data);
}
// Beginning of sample API calls
// getXIDInfo returns information about an XID if the caller has permission to access it
function getXIDInfo(authToken, xid) {
// accessing information about an XID requires that we tell the server where the access
// is.
var url = ";
xhrCall((api.aXContent + "/" + xid + "?url=" + escape(url)), null, authToken,
function(resp) {
DEBUG("XID Info: " + JSON.stringify(resp.info));
},
function(code, resp) {
DEBUG("failed to get XID info; code = " + code + ", " + JSON.stringify(resp));
});
}
// createXID creates an XID; it uses the first policy in the list of user policies.
function createXID(authToken, policies) {
// creating an XID requires that we tell the server where the posted content will live
var url = ";
// creating an XID requires that the client pass the key. this key
// is the hexadecimal encoding of an arbitrary length array of bytes
// so this will be a string of even length.
var key = "00112233ddeeff";
// xpid is the policy ID that the XID will use for access control. It must
// be obtained by choosing one of the policies in the user's list of policies.
var xpid = policies[0].xpid;
// scheme gives information about how the client will be ciphering/encrypting the
// data. Currently only "default" is supported.
var scheme = policies[0].cipherscheme;
// make the actual call
xhrCall(api.aXContent, {xpid: xpid, scheme: scheme, url: url, key: key}, authToken,
function(resp) {
DEBUG("Created XID: " + JSON.stringify(resp.info));
getXIDInfo(authToken, resp.info.xid);
},
function(code, resp) {
DEBUG("failed to create XID; code = " + code + ", " + JSON.stringify(resp));
});
}
// starts the chain of (asynchronous) tests by getting the user policies
function afterAuth(authToken) {
// make a call to get the user's list of policies. when we get that list
// make the call to create an XID
xhrCall(api.aUserPS, null, authToken,
function(resp) {
DEBUG("User policies: " + JSON.stringify(resp.info));
createXID(authToken, resp.info);
},
function(code, resp) {
DEBUG("failed to get user policies; code = " + code + ", " + JSON.stringify(resp));
});
}
// authenticates against the server and on successful authentication gets the
// rest of the tests running. The important outcome of the authentication
// is the auth token, as all authenticated APIs require that.
function authTest(after) {
// authentication requires email address and password of a valid account
xhrCall(api.uAuth, {'email':'put in account email address', 'password':'put in account password'}, null,
function(resp) {
// DEBUG("got response " + JSON.stringify(resp));
// resp.result should ALWAYS be "OK"
after(resp.info.authToken);
},
function(code, resp) {
DEBUG("auth failed with code " + code + ": " + JSON.stringify(resp));
});
}
// entry point for the onload event handler
function runtest() {
authTest(afterAuth);
}
| |