B-C-ME2SR3

Test Akamai API with postman and Javascript #3

Blog Post created by B-C-ME2SR3 Employee on May 10, 2017

It's time to share full Javascript code for "Pre-request Script" feature of postman. To implement code for Akamai API, we do have to use "SHA256" hash algorithm and "HMAC" message authentication code. Javascript itself does not provide such a functionality. So we need to get some help from open source libraries. Very famous one for this purpose in Javascript world is CryptoJS library. Fortunately, postman support embedded CryptoJS and we can use it with prefix "CryptoJS", e.g. "CryptoJS.SHA256(Data)". 

 

Let's see full code for "Pre-request Script".

 

var AccessToken;
var BaseURL;
var ClientSecret;
var ClientToken;
var ReqType;
var ReqPath;
var Data;

// Pick up environment variables into credentials object
var credentials = {
  baseURL: postman.getEnvironmentVariable("baseURL"),
  accessToken: postman.getEnvironmentVariable("accessToken"),
  clientToken: postman.getEnvironmentVariable("clientToken"),
  clientSecret: postman.getEnvironmentVariable("clientSecret")
}

// Define variables for calling Akamai API
var endpoint = {
  method: request.method,
  host: postman.getEnvironmentVariable("baseURL"),
  scheme: request.url.substring(0, request.url.indexOf("://")-1),
  reqPath: request.url.substring(request.url.indexOf(credentials.baseURL) + credentials.baseURL.length, request.url.length)
}

// Enhancing Date to have formatting functionality
Date.prototype.format = function(f) {
  if (!this.valueOf()) return " ";

  var weekName = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
  var d = this;

  return f.replace(/(yyyy|yy|MM|dd|E|hh|mm|ss|a\/p)/gi, function($1) {
    switch ($1) {
      case "yyyy": return d.getFullYear();
      case "yy": return (d.getFullYear() % 1000).zf(2);
      case "MM": return (d.getMonth() + 1).zf(2);
      case "dd": return d.getDate().zf(2);
      case "E": return weekName[d.getDay()];
      case "HH": return d.getHours().zf(2);
      case "hh": return ((h = d.getHours() % 12) ? h : 12).zf(2);
      case "mm": return d.getMinutes().zf(2);
      case "ss": return d.getSeconds().zf(2);
      case "a/p": return d.getHours() < 12 ? "AM" : "PM";
      default: return $1;
    }
  });
};

// Utility functions for Date formatter
String.prototype.string = function(len){var s = '', i = 0; while (i++ < len) { s += this; } return s;};
String.prototype.zf = function(len){return "0".string(len - this.length) + this;};
Number.prototype.zf = function(len){return this.toString().zf(len);};

// Generating GUID
var guid = (function() {
  function s4() { return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1); }
  return function() { return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); };
})();

// Generate Akamai signature Data
function generateSignatureData(ReqType,BaseURL,ReqPath,Data,ClientToken,AccessToken,TimeStamp,Nonce) {
  if ((ReqType == "POST") || (ReqType == "PUT")) {
    var SignatureData = ReqType + String.fromCharCode(9);
    SignatureData += "https" + String.fromCharCode(9);
    SignatureData +=  BaseURL + String.fromCharCode(9);
    SignatureData +=  ReqPath +  String.fromCharCode(9);
    //SignatureData += String.fromCharCode(9) + CryptoJS.enc.Base64.stringify(CryptoJS.SHA256(Data)) + String.fromCharCode(9);
    SignatureData += String.fromCharCode(9) + CryptoJS.SHA256(Data).toString(CryptoJS.enc.Base64) + String.fromCharCode(9);
    SignatureData += "EG1-HMAC-SHA256 "
    SignatureData += "client_token=" + ClientToken + ";"
    SignatureData += "access_token=" + AccessToken + ";"
    SignatureData += "timestamp=" + TimeStamp  + ";"
    SignatureData += "nonce=" + Nonce + ";"

    return SignatureData;
  }
  else {
    var SignatureData = ReqType + String.fromCharCode(9);
    SignatureData += "https" + String.fromCharCode(9);
    SignatureData +=  BaseURL + String.fromCharCode(9);
    SignatureData +=  ReqPath +  String.fromCharCode(9) + String.fromCharCode(9) + String.fromCharCode(9); 
    SignatureData += "EG1-HMAC-SHA256 "
    SignatureData += "client_token=" + ClientToken + ";"
    SignatureData += "access_token=" + AccessToken + ";"
    SignatureData += "timestamp=" + TimeStamp  + ";"
    SignatureData += "nonce=" + Nonce + ";"
   
    return SignatureData;
  }
}

// Generate Authorization Header - Result of this function have to set into request header
function generateAuthorizationHeader(ClientToken,AccessToken,TimeStamp,Nonce,Signature) {
  var AuthorizationHeader = "EG1-HMAC-SHA256 "
  AuthorizationHeader += "client_token=" + ClientToken + ";"
  AuthorizationHeader += "access_token=" + AccessToken + ";"
  AuthorizationHeader += "timestamp=" + TimeStamp + ";"
  AuthorizationHeader += "nonce=" + Nonce + ";"
  AuthorizationHeader += "signature=" + Signature

  return AuthorizationHeader;
}

// Generate Hash - Using sandbox CryptoJS library
function generateHash(key,data) {
  var signature = CryptoJS.HmacSHA256(data, key);
  signature = signature.toString(CryptoJS.enc.Base64);
 
  return signature;
}

// Send request to API endpoint
function submitRequest() {
  ClientToken = credentials.clientToken;
  AccessToken = credentials.accessToken;
  BaseURL = credentials.baseURL;
  ClientSecret = credentials.clientSecret;
  ReqPath = endpoint.reqPath;
  ReqType = endpoint.method;
  Data = request.data;
 
  var d = new Date();
  var month = d.getUTCMonth()+1;
  var TimeStamp = d.getUTCFullYear() + month.zf(2) + d.getUTCDate().zf(2) + "T" + d.getUTCHours().zf(2) + ":" + d.getUTCMinutes().zf(2) + ":" + d.getUTCSeconds().zf(2) + "+0000";
  var Nonce = guid();
  var SignatureData = generateSignatureData(ReqType,BaseURL,ReqPath,Data,ClientToken,AccessToken,TimeStamp,Nonce);
  var SigningKey = generateHash(ClientSecret,TimeStamp);
  var Signature = generateHash(SigningKey,SignatureData);
  var AuthorizationHeader = generateAuthorizationHeader(ClientToken,AccessToken,TimeStamp,Nonce,Signature);

  // Add created authorization header as a Header of postman collecitons
  postman.setEnvironmentVariable('authorizationHeader', AuthorizationHeader);
}

submitRequest();

 

 

If you have interests, you can deep dive into each of code lines. But if you wants to use it with postman, just follow steps described below. I assumed you've already prepared postman environment for your contract. 

 

[ Step1. Create a new collection ]

Before we define specific API request, we need to create collection. You can find folder icon on the left pan. Click it to add a new collection. This is not technical at all :-). 

 

[ Step2. Add a new request ]

A collection is a container for requests. You can think of a request as a specific call for API method. I've picked up a purge method from developer.akamai.com. This method required to be called "POST". Please fill out URL box with your base URL and path, /ccu/v2/queues/default. 

 

 URL : Content Control Utility Resources 

 

 

Let's back to the top of this article to copy Javascript code to be filled with "Pre-request Script". All you need to do is Ctrl-C then Ctrl-V. Once it's filled with script, blue bullet will be there on the right side of "Pre-request Script" tab.

 

 

We need to add some headers into headers tab. As I mentioned earlier, double curly brace will be changed values from environment or code. Code line #132 calls postman.setEnvironmentVariable method to set "authorizationHeader" value. Don't forget to add "Content-Type" as a "application/json". Some of Akamai API wants to set Content-Type as another value but generally it is "application/json"

 

 

We are almost done to set-up a request. This is purge request with "POST" method. So we need to specify what contents have to be purged from Akamai Intelligent Platform on HTTP request body. Let's move on to "Body" tab and add JSON formatted purge request details.

 

 

[ Step3. Do test Akamai API...!! ]

Are you ready to call the request? Let's click blue colored "Send" button on right side of the URL box. It will take a few second to be queued request. Then the result will be displayed on the bottom of the screen.

 

 

Cool. Purge request accepted by machines that is in charge of it. If the request worked well, save the request to be used in the future. "Save" button is located beside of "Send" button. 

 

I'm using postman to call several Akamai APIs nowadays. "Purge" is the best one that I love, but I'm using the code for Media Report API and Property Manager API as well. I don't think there's big errors on script, but if you find anything, let me know it. I will make github repository for this script soon and will share it here. 

 

Thanks!

 

// Previous Articles

Test Akamai API with postman and Javascript #1 

Test Akamai API with postman and Javascript #2 

 

- NoPD -

Outcomes