Skip to content

KX Connect (JS) appendix

JS Dependencies

/** Core dependencies **/
npm
node-fetch
crypto-js
crypto
js-base64
hmacsha1
utf8
uuid

/** Additional **/
// For CSV export
jsonexport
fs

// For websocket connection
ws

connectSample.js

// Import dependencies
const fetch = require("node-fetch");
global.Headers = fetch.Headers;
const CryptoJS = require("crypto-js");
const Crypto = require("crypto");
const Base64 = require("js-base64").Base64;
const HMACSHA1 = require("hmacsha1");
const UTF8 = require("utf8");
const UUID = require("uuid/v4");
// Include this is you wish to use the CSV export function
// var ex = require("./export");


// Get input parameters
var HTTP_HOST = "http://localhost:8080";
var USERNAME = "Administrator";
var PASSWORD = "password";
var METHOD_NAME = "getMem";

var input = process.argv.slice(2);

if(input.length > 0){
  if(input.length == 4){
    HTTP_HOST = "http://" + input[0];
    USERNAME = input[1];
    PASSWORD = input[2];
    METHOD_NAME = input[3];

  } else {
    console.log("Expected 4 parameters: HOST:PORT USERNAME PASSWORD METHOD. Received params: " + input.length);
    console.log("Continuing using default parameters");
  }
}

// Define variables
const BASE_URL = HTTP_HOST + "/connect/api";
const METHOD_GROUP = "monPublic";
const METHOD_REQUEST = METHOD_NAME + "Req";
const PARAMS = {};
const CONTENT_TYPE = "application/json";
var id = UUID();

// Define login info
var LOGIN_URL = BASE_URL + "/auth/login";
var LOGIN_DATA = {
  "msg" : [{
    "username" : USERNAME, 
    "password" : PASSWORD 
  }], 
  "type" : "LoginReq", 
  "id" : id, 
  "date" : new Date().toUTCString()
};

// All users accessing Connect API must login before sending further requests
// Call login API
loginRequest(LOGIN_URL, LOGIN_DATA) 

function loginRequest(url, data) {
  console.log("Making a login request to " + LOGIN_URL + " with user " + USERNAME);

  return fetch(url, {
    credentials: "same-origin",
    method: "POST",
    body: JSON.stringify(data),
    headers: new Headers({
      "Content-Type": CONTENT_TYPE
    }),
  })
  // If response, call SendQuery function
  .then(response => {
    sendQuery(response)
  })
  .catch(error =>{
    console.error(error)
  })
}


var sendQuery = function(response){
  // If login is unsuccessful, return status code
  if (response.status !== 200) {
        console.log("Error. Status Code: " + response.status)
        return;
  }

  // If login is successful, call REST API
  response.json().then(function(data) {

    // authPath is used in stringToSign and the requestPath is the REST call
    var requestPath = BASE_URL + "/" + METHOD_GROUP + "/" + METHOD_NAME
    var authPath = "/connect/api/" + METHOD_GROUP + "/" + METHOD_NAME
    // Get session ID from login response
    var sessionId = data["msg"][0]["sessionId"];
    var date = new Date().toUTCString();

    QUERY_DATA = {
      "type" : METHOD_REQUEST,
      "msg" : [
        PARAMS
      ],
      "id" : id,
      "date" : date
    };

    // Encrypt authorization info - see KX Connect documents
    var jsonData = JSON.stringify(QUERY_DATA);

    // Content message must be hashed using MD5
    var queryMd5Str = CryptoJS.MD5(jsonData).toString();

    // Create signed input string
    var stringToSign = "POST\n" + authPath + "\n" + USERNAME + "\n" + queryMd5Str +  "\n" + CONTENT_TYPE + "\n" + date + "\n" + sessionId;
    console.log("stringToSign: " + stringToSign);

    // Create signature
    var hmacEncStr = CryptoJS.HmacSHA1(stringToSign, sessionId);
    console.log("HMAC:" + hmacEncStr);
    var signature = hmacEncStr.toString(CryptoJS.enc.Base64);

    // Authorization HTTP header = username + last 5 characters of the session Id : signature value
    var authorization = USERNAME + sessionId.substring(sessionId.length - 5) + ":" + signature;
    console.log("Auth:" + authorization);

    // Send REST API request
    apiRequest(requestPath, authorization, jsonData);
  });
};

// Send API request
function apiRequest(url, auth, data) {
  return fetch(url, {
    credentials: "same-origin",
    method: "POST",
    body: data,
    headers: new Headers({
      "Content-Type": CONTENT_TYPE,
      "Authorization": auth
    }),
  })
  .then(response => {
    response.text().then(function(data) {
      console.log(data);
      // If you wish to export to CSV
      // ex.CSV(data, METHOD_NAME);
    })
  })
  .catch(error => console.error(error))
}

export.js

// Import Dependencies 
const jsonexport = require("jsonexport");
const fs = require("fs");

// Export to CSV 
exports.CSV = function (data, method){
    // Create save filepath
    var date = new Date().toISOString().substring(0, 10);
    var csvFilepath = "/tmp/" + method + "_" + date + ".csv";

    // Parse json object
    var jsonData = JSON.parse(data)["msg"];

    // Specify header order
    var options = {};
    // var options = {headers: ["time", "sym", "physical", "virtual"]};

    // Convert from JSON to CSV
    jsonexport(jsonData, options, function(err, csv){
      // Write to file
      fs.writeFile(csvFilepath, csv, function(err){
        if(err) return console.log(err);
      });
    });
    console.log("Export to CSV complete");
  }