mrajagopal/nodejs-ssllabs-api

View on GitHub
ssllabs-api.js

Summary

Maintainability
A
1 hr
Test Coverage
#!/usr/bin/env node


"use strict";

var util = require('util');
var https = require('https');
var apiVersionPath = "/api/v2";
var intervalObj;
var events = require('events');
var ANALYZE_POLL_INTERVAL = 30000;
var debug = true;
var apiHost = 'api.ssllabs.com';
var apiLocation = 'https://' + apiHost + apiVersionPath;
var userAgent = "nodejs-ssllabs-api v0.0.1 (dev $Id$)";

function debugLog(log){
  if (debug === true){
    console.log(log);
  }
}

// Instantiate if one not already created/new'ed
function SslLabsApi(hostToAnalyze, consoleDebug){
  if (!(this instanceof SslLabsApi)){
    return new SslLabsApi(hostToAnalyze, consoleDebug);
  }

  this.options = {
    host: apiHost,
    method: 'GET',
    path: '/'
  };

  events.EventEmitter.call(this);
  this.hostToAnalyze = hostToAnalyze;
  this.httpReqTimeoutValueInMs = 5000;
  debug = consoleDebug;
}

// extent the SslLabsApi object using EventEmitter
util.inherits(SslLabsApi, events.EventEmitter);


SslLabsApi.prototype._emitError = function _emitError(e){
  debugLog(e);
  clearInterval(intervalObj);
  this.emit('error', e);
};

SslLabsApi.prototype.version = function version(){
  return ('\r\nUser Agent  : ' + userAgent + 
          '\r\nAPI Location: ' + apiLocation
          + '\r\n');
}

SslLabsApi.prototype.info = function info(){
  this.options.path = apiVersionPath + '/info';
  var req = https.request(this.options, this.infoResponse.bind(this));
  req.setTimeout(this.httpReqTimeoutValueInMs, function() {
    req.abort();
  });

  req.on('error', this._emitError.bind(this));
  req.end();
};


SslLabsApi.prototype.analyzeHost = function analyzeHost(){
  this.options.path = apiVersionPath + '/analyze?host=' + this.hostToAnalyze;
  debugLog(this.options.path);
  var req = https.request(this.options, this.analyzeResponse.bind(this));
  req.setTimeout(this.httpReqTimeoutValueInMs, function() {
    req.abort();
  });

  req.on('error', this._emitError.bind(this));
  req.end();
};


SslLabsApi.prototype.analyzeHostCached = function analyzeHostCached(maxAge){
  if(maxAge === undefined){
    this.options.path = apiVersionPath + '/analyze?host=' + this.hostToAnalyze + '&fromCache=on&all=done';
  }
  else{
    this.options.path = apiVersionPath + '/analyze?host=' + this.hostToAnalyze + '&fromCache=on&all=done' + '&maxAge=' + maxAge;
  }
  debugLog(this.options.path);
  var req = https.request(this.options, this.analyzeResponse.bind(this));

  function handleTimeout(){
    debugLog('Request timed out');
    clearInterval(intervalObj);
    req.abort();
  }

  req.setTimeout(this.httpReqTimeoutValueInMs, handleTimeout);
  req.end();
  this.startPoll();

 req.on('error', this._emitError.bind(this));
};

SslLabsApi.prototype.analyzeHostNew = function analyzeHostNew(){
  debugLog('2 hostToAnalyze = ' + this.hostToAnalyze);
  this.options.path = apiVersionPath + '/analyze?host=' + this.hostToAnalyze + '&startNew=on&all=done';
  debugLog(this.options.path);
  var req = https.request(this.options, this.analyzeResponse.bind(this));

  function handleTimeout(){
    debugLog('Request timed out');
    clearInterval(intervalObj);
    req.abort();
  }

  req.setTimeout(this.httpReqTimeoutValueInMs, handleTimeout);
  req.on('error', this._emitError.bind(this));
  req.end();
  this.startPoll();
};

SslLabsApi.prototype.getEndpointData = function getEndpointData(endpoint){
  this.options.path = apiVersionPath + '/getEndpointData?host=' + this.hostToAnalyze + '&s=' + endpoint;
  var req = https.request(this.options, this.endpointResponse.bind(this));

  function handleTimeout(){
    debugLog('Request timed out');
    clearInterval(intervalObj);
    req.abort();
  }

  req.setTimeout(this.httpReqTimeoutValueInMs, handleTimeout);
  req.on('error', this._emitError.bind(this));
  req.end();
};

SslLabsApi.prototype.getStatusCodes = function getStatusCodes(){
  this.options.path = apiVersionPath + '/getStatusCodes';
  var req = https.request(this.options, this.statusCodesResponse.bind(this));

  function handleTimeout(){
    debugLog('Request timed out');
    clearInterval(intervalObj);
    req.abort();
  }

  req.setTimeout(this.httpReqTimeoutValueInMs, handleTimeout);
  req.end();
  req.on('error', this._emitError.bind(this));
};


SslLabsApi.prototype.analyzeResponse = function analyzeResponse(resp){
  var self = this;
  var respBody = '';

  resp.on('data', function (chunk){
    respBody += chunk;
  });

  resp.on('Error', function(e){
    console.log('This is the error dump', e);
  });

  resp.on('end', function(){
    //debugLog(respBody);
    if (respBody.length){
      var jsonResp = JSON.parse(respBody);
      //console.log(respBody);
      if (jsonResp.status) {
        if(jsonResp.status === "READY"){
          self.emit('analyzeData', /*jsonResp*/respBody);
          clearInterval(intervalObj);
          debugLog("assessment complete");
        } else if((jsonResp.status === "DNS") || (jsonResp.status === "IN_PROGRESS")){
          debugLog(jsonResp.status);
        }else if(jsonResp.status === "ERROR"){
          self._emitError(jsonResp.statusMessage);
        }else{
          self._emitError('Unknown Response Received');
        }
      } else{
        self._emitError(jsonResp);
      }
    }else{
      self._emitError('No Response Body Received');
    }
  });
};

function processResponse(obj, resp, eventType){
  var self = obj;
  var respBody = '';
  resp.on('data', function (chunk){
    respBody += chunk;
  });

  resp.on('end', function(){
    var jsonResp = JSON.parse(respBody);
    self.emit(eventType, jsonResp);
  });
}


SslLabsApi.prototype.endpointResponse = function endpointResponse(resp){
  processResponse(this, resp, 'endpointData');
};


SslLabsApi.prototype.statusCodesResponse = function statusCodesResponse(resp){
  processResponse(this, resp, 'statusCodesData');
};


SslLabsApi.prototype.infoResponse = function infoResponse(resp){
  processResponse(this, resp, 'infoResponse');
};


SslLabsApi.prototype.pollAnalyzeRequest = function pollAnalyzeRequest() {
  this.options.path = apiVersionPath + '/analyze?host=' + this.hostToAnalyze;
  var req = https.request(this.options, this.analyzeResponse.bind(this));

  function handleTimeout(){
    debugLog('Request timed out');
    clearInterval(intervalObj);
    req.abort();
  }

  req.setTimeout(this.httpReqTimeoutValueInMs, handleTimeout);
  req.on('error', this._emitError.bind(this));
  req.end();
};


SslLabsApi.prototype.startPoll = function startPoll(){
  debugLog('4 hostToAnalyze = ' + this.hostToAnalyze);
  intervalObj = setInterval(this.pollAnalyzeRequest.bind(this), ANALYZE_POLL_INTERVAL);
};


SslLabsApi.prototype.getEndpointIpAddr = function getEndpointIpAddr(data) {
  return data.endpoints[0].ipAddress;
};


module.exports = SslLabsApi;