From 3984adcbe817f58a4d11f79324fa19484432bee6 Mon Sep 17 00:00:00 2001
From: Yaron Schwimmer <yaron@perimeterx.com>
Date: Mon, 30 Jul 2018 15:49:56 +0300
Subject: [PATCH 1/9] Dev fix net cb error (#58)

* removed request with no response option

* fixed tests
---
 lib/pxapi.js            |   2 +-
 lib/pxclient.js         |   2 +-
 lib/pxhttpc.js          |   5 +-
 lib/request.js          |   8 -
 test/pxapi.test.js      |   2 +-
 test/pxconfig.test.js   |   3 +-
 test/pxenforcer.test.js |  20 +-
 test/unit.test.js       | 430 ----------------------------------------
 8 files changed, 17 insertions(+), 455 deletions(-)
 delete mode 100644 test/unit.test.js

diff --git a/lib/pxapi.js b/lib/pxapi.js
index 5641cd9d..c8ad9731 100644
--- a/lib/pxapi.js
+++ b/lib/pxapi.js
@@ -99,7 +99,7 @@ function callServer(pxCtx, callback) {
     }
 
     pxCtx.hasMadeServerCall = true;
-    return pxHttpc.callServer(data, reqHeaders, config.SERVER_TO_SERVER_API_URI, 'query', false, callback);
+    return pxHttpc.callServer(data, reqHeaders, config.SERVER_TO_SERVER_API_URI, 'query', callback);
 }
 
 
diff --git a/lib/pxclient.js b/lib/pxclient.js
index f61d0362..c78281f5 100644
--- a/lib/pxclient.js
+++ b/lib/pxclient.js
@@ -90,7 +90,7 @@ class PxClient {
     }
 
     callServer(data, path, headers, cb) {
-        pxHttpc.callServer(data, headers, path, 'activities', true);
+        pxHttpc.callServer(data, headers, path, 'activities');
         if (cb) {
             cb();
         }
diff --git a/lib/pxhttpc.js b/lib/pxhttpc.js
index 1e8b3712..e7920282 100644
--- a/lib/pxhttpc.js
+++ b/lib/pxhttpc.js
@@ -16,8 +16,8 @@ module.exports = {
  * @param {string} callType - indication for a query or activities sending
  * @param {Function} callback - callback function.
  */
-function callServer(data, headers, uri, callType, ignoreResponse, callback) {
-    callback = callback || ((err) => { pxLogger.debug(`callServer callback missing. Error: ${err}`) });
+function callServer(data, headers, uri, callType, callback) {
+    callback = callback || ((err) => { err && pxLogger.debug(`callServer default callback. Error: ${err}`); });
     const config = pxConfig.conf;
     const callData = {
         url: `https://${config.SERVER_HOST}${uri}`,
@@ -26,7 +26,6 @@ function callServer(data, headers, uri, callType, ignoreResponse, callback) {
     };
 
     callData.timeout = callType === 'query' ? config.API_TIMEOUT_MS : config.ACTIVITIES_TIMEOUT;
-    callData.ignoreResponse = ignoreResponse;
 
     try {
         request.post(callData, function (err, response) {
diff --git a/lib/request.js b/lib/request.js
index 8a5e065b..e5cfb05b 100644
--- a/lib/request.js
+++ b/lib/request.js
@@ -20,18 +20,10 @@ const request = {
 function makeRequest(options, cb) {
     options.agent = keepAliveAgent;
     try {
-        if (options.ignoreResponse) {
-            return makeRequestWithNoResponse(options);
-        }
         p(options, cb)
     } catch (e) {
         pxLogger.error(`Error making request: ${e.message}`);
     }
 }
 
-
-function makeRequestWithNoResponse(options) {
-    p(options);
-}
-
 module.exports = request;
\ No newline at end of file
diff --git a/test/pxapi.test.js b/test/pxapi.test.js
index 00eb4721..f17c0436 100644
--- a/test/pxapi.test.js
+++ b/test/pxapi.test.js
@@ -30,7 +30,7 @@ describe('PX API - pxapi.js', () => {
         let pxconfig = require('../lib/pxconfig');
         pxconfig.init(params, new PxClient());
         config = pxconfig.mergeDefaults(params);
-        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, ignore, callback) => {
+        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, callback) => {
             return callback(data)
         });
     });
diff --git a/test/pxconfig.test.js b/test/pxconfig.test.js
index 6463c59f..abb3f615 100644
--- a/test/pxconfig.test.js
+++ b/test/pxconfig.test.js
@@ -17,7 +17,8 @@ describe('PX Configurations - pxconfig.js', () => {
             blockingScore: 60,
             debugMode: true,
             ipHeader: 'x-px-true-ip',
-            maxBufferLength: 1
+            maxBufferLength: 1,
+            customRequestHandler: null
         };
 
         pxconfig = require('../lib/pxconfig');
diff --git a/test/pxenforcer.test.js b/test/pxenforcer.test.js
index 64d095bd..d2b7d4b5 100644
--- a/test/pxenforcer.test.js
+++ b/test/pxenforcer.test.js
@@ -43,7 +43,7 @@ describe('PX Enforcer - pxenforcer.js', () => {
     });
 
     it('enforces a call in a disabled module', (done) => {
-        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, ignore, callback) => {
+        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, callback) => {
             return callback ? callback(null, data) : '';
         });
         params.enableModule = false;
@@ -56,7 +56,7 @@ describe('PX Enforcer - pxenforcer.js', () => {
     });
 
     it('enforces a call in an enabled module', (done) => {
-        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, ignore, callback) => {
+        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, callback) => {
             return callback ? callback(null, data) : '';
         });
         enforcer = new PxEnforcer(params, new PxClient());
@@ -67,8 +67,8 @@ describe('PX Enforcer - pxenforcer.js', () => {
         });
     });
 
-    it.only('uses first party to get client', (done) => {
-        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, ignore, callback) => {
+    it('uses first party to get client', (done) => {
+        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, callback) => {
             return callback ? callback(null, data) : '';
         });
         let reqStub = sinon.stub(request, 'get').callsFake((data, callback) => {
@@ -86,7 +86,7 @@ describe('PX Enforcer - pxenforcer.js', () => {
     });
 
     it('uses first party for xhr post request', (done) => {
-        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, ignore, callback) => {
+        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, callback) => {
             return callback ? callback(null, data) : '';
         });
         let reqStub = sinon.stub(request, 'post').callsFake((data, callback) => {
@@ -106,7 +106,7 @@ describe('PX Enforcer - pxenforcer.js', () => {
     });
 
     it('uses first party for xhr get request', (done) => {
-        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, ignore, callback) => {
+        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, callback) => {
             return callback ? callback(null, data) : '';
         });
         let reqStub = sinon.stub(request, 'get').callsFake((data, callback) => {
@@ -126,7 +126,7 @@ describe('PX Enforcer - pxenforcer.js', () => {
     });
 
     it('uses first party with pxvid cookie', (done) => {
-        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, ignore, callback) => {
+        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, callback) => {
             return callback ? callback(null, data) : '';
         });
         let reqStub = sinon.stub(request, 'post').callsFake((data, callback) => {
@@ -147,7 +147,7 @@ describe('PX Enforcer - pxenforcer.js', () => {
     });
 
     it('uses first party for xhr and passed trough bodyParser', (done) => {
-        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, ignore, callback) => {
+        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, callback) => {
             return callback ? callback(null, data) : '';
         });
         let reqStub = sinon.stub(request, 'post').callsFake((data, callback) => {
@@ -167,7 +167,7 @@ describe('PX Enforcer - pxenforcer.js', () => {
     });
 
     it('uses upper case for xhr', (done) => {
-        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, ignore, callback) => {
+        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, callback) => {
             return callback ? callback(null, data) : '';
         });
         let reqStub = sinon.stub(request, 'post').callsFake((data, callback) => {
@@ -187,7 +187,7 @@ describe('PX Enforcer - pxenforcer.js', () => {
     });
 
     it('should not use first party paths if originated from mobile', (done) => {
-        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, ignore, callback) => {
+        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, callback) => {
             data.score = 100;
             data.action = 'b';
             return callback ? callback(null, data) : '';
diff --git a/test/unit.test.js b/test/unit.test.js
deleted file mode 100644
index 31e5b40a..00000000
--- a/test/unit.test.js
+++ /dev/null
@@ -1,430 +0,0 @@
-'use strict';
-
-const should = require('should');
-const sinon = require('sinon');
-const rewire = require("rewire");
-const pxutil = require('../lib/pxutil');
-const request = require('../lib/request');
-const pxhttpc = require('../lib/pxhttpc');
-const pxapi = rewire('../lib/pxapi');
-const PxClient = rewire('../lib/pxclient');
-const PxEnforcer = require('../lib/pxenforcer')
-const originalTokenValidator = require('../lib/pxoriginaltoken');
-
-describe('PX Utils - pxutils.js', () => {
-    let pxconfig;
-    let params;
-
-    beforeEach(() => {
-        params = {
-            pxAppId: 'PX_APP_ID',
-            cookieSecretKey: 'PX_COOKIE_SECRET',
-            authToken: 'PX_AUTH_TOKEN',
-            sendPageActivities: true,
-            blockingScore: 60,
-            debugMode: true,
-            ipHeader: 'x-px-true-ip',
-            maxBufferLength: 1
-        };
-
-        pxconfig = require('../lib/pxconfig');
-        pxconfig.init(params, new PxClient());
-    });
-
-    it('should generate headers array from headers object', (done) => {
-        const formattedHeaders = pxutil.formatHeaders({K: 'v'});
-        (Object.prototype.toString.call(formattedHeaders)).should.be.exactly('[object Array]');
-        formattedHeaders[0]['name'].should.be.exactly('K');
-        formattedHeaders[0]['value'].should.be.exactly('v');
-        return done();
-    });
-});
-
-describe('PX Configurations - pxconfig.js', () => {
-    let pxconfig;
-    let params;
-
-    beforeEach(() => {
-        params = {
-            pxAppId: 'PX_APP_ID',
-            cookieSecretKey: 'PX_COOKIE_SECRET',
-            authToken: 'PX_AUTH_TOKEN',
-            sendPageActivities: true,
-            blockingScore: 60,
-            debugMode: true,
-            ipHeader: 'x-px-true-ip',
-            maxBufferLength: 1
-        };
-
-        pxconfig = require('../lib/pxconfig');
-    });
-
-    it('should set baseUrl to sapi-<appid>.perimeterx.net', (done) => {
-        params.pxAppId = 'PXJWbMQarF';
-        pxconfig.init(params, new PxClient());
-        const conf = pxconfig.conf;
-        conf.SERVER_HOST.should.be.exactly(`sapi-${params.pxAppId.toLowerCase()}.perimeterx.net`)
-        done();
-    });
-
-    it('blocking score should be 80', (done) => {
-        params.blockingScore = 80;
-        pxconfig.init(params, new PxClient());
-        const conf = pxconfig.conf;
-        conf.BLOCKING_SCORE.should.be.exactly(80);
-        done();
-    });
-
-    it('getUserIp function should be overridden', (done) => {
-        params.getUserIp = function () {
-            return '1.2.3.4';
-        };
-
-        pxconfig.init(params, new PxClient());
-        const conf = pxconfig.conf;
-        conf.GET_USER_IP().should.be.exactly('1.2.3.4');
-        done();
-    });
-
-    it('requestHandler function should be overridden', (done) => {
-        params.customRequestHandler = function () {
-            return 'Blocked';
-        };
-
-        pxconfig.init(params, new PxClient());
-        const conf = pxconfig.conf;
-        conf.CUSTOM_REQUEST_HANDLER().should.be.exactly('Blocked');
-        done();
-    });
-
-    it('should set enableModule to false', () => {
-        params.enableModule = false;
-        pxconfig.init(params, new PxClient());
-        const conf = pxconfig.conf;
-        conf.ENABLE_MODULE.should.be.exactly(false);
-    });
-
-    it('should set sendPageActivities to false', () => {
-        params.sendPageActivities = false;
-        pxconfig.init(params, new PxClient());
-        const conf = pxconfig.conf;
-        conf.SEND_PAGE_ACTIVITIES.should.be.exactly(false);
-    });
-
-    it('should set debugMode to true', () => {
-        params.sendPageActivities = true;
-        pxconfig.init(params, new PxClient());
-        const conf = pxconfig.conf;
-        conf.DEBUG_MODE.should.be.exactly(true);
-    });
-
-    it('customLogo should be overridden', () => {
-        params.customLogo = 'http://www.google.com/logo.jpg';
-        pxconfig.init(params, new PxClient());
-        const conf = pxconfig.conf;
-        conf.CUSTOM_LOGO.should.be.exactly('http://www.google.com/logo.jpg');
-    });
-
-    it('jsRef should be overridden', () => {
-        params.jsRef = ['http://www.google.com/script.js'];
-        pxconfig.init(params, new PxClient());
-        const conf = pxconfig.conf;
-        conf.JS_REF[0].should.equal('http://www.google.com/script.js');
-    });
-
-    it('cssRef should be overridden', () => {
-        params.cssRef = ['http://www.google.com/stylesheet.css'];
-        pxconfig.init(params, new PxClient());
-        const conf = pxconfig.conf;
-        conf.CSS_REF[0].should.equal('http://www.google.com/stylesheet.css');
-    });
-});
-
-describe('PX API - pxapi.js', () => {
-    let params;
-    let config;
-    let stub;
-    beforeEach(() => {
-        params = {
-            pxAppId: 'PX_APP_ID',
-            cookieSecretKey: 'kabum',
-            authToken: 'PX_AUTH_TOKEN',
-            sendPageActivities: true,
-            blockingScore: 60,
-            debugMode: true,
-            ipHeader: 'x-px-true-ip',
-            maxBufferLength: 1
-        };
-
-        let pxconfig = require('../lib/pxconfig');
-        config = pxconfig.mergeDefaults(params);
-        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, ignore, callback) => {
-            return callback(data)
-        });
-    });
-
-    afterEach(() => {
-        stub.restore();
-    });
-    it('should add px_orig_cookie to risk_api when decryption fails', (done) => {
-        //Stubbing the pxhttpc callServer functions
-
-
-        //Using rewire to get callServer function
-        const pxApiCallServerFunc = pxapi.__get__('callServer');
-
-        // Prepare pxCtx
-        const pxCtx = {
-            ip: '1.2.3.4',
-            fullUrl: 'stub',
-            vid: 'stub',
-            uuid: 'stub',
-            uri: 'stub',
-            headers: 'stub',
-            httpVersion: 'stub',
-            s2sCallReason: 'cookie_decryption_failed',
-            httpMethod: 'stub',
-            getCookie: () => { return 'abc'}
-        }
-
-        pxApiCallServerFunc(pxCtx, data => {
-            data.additional.px_orig_cookie.should.equal('abc')
-            done();
-        });
-    });
-
-    it('token v3 - should add originalUuid, vid and decodedOriginalToken to pxCtx when original token decryption succeeds', (done) => {
-        const pxCtx = {
-            cookies:{
-                _px3:'aaaa'
-            },
-            originalToken: '68a1bf96ab3af2e0683a377d332b125dda3e195ee56cf3ce4d61b99cd0860dc6:xTMRZvJnzxM=:1000:0pjajaPCjssb2HjG2436zyFXIvIEbE87nFBrHEQPDRT7fqiQ5RA05+njsLUVpOtdJjLvWNNAlSG70DW2wqWM5VmF9UR420/wxPkx6Ebyz/L9q7Mxk5fcdF8p+dGcMc3uD7Qh8y3WiPSN389cXhfKfMttUABQYvRpOxo7rMC+ngpHEVYg+lfBZCliHB1PZKLy'
-        }
-
-        originalTokenValidator.evalCookie(pxCtx, config);
-        pxCtx.originalUuid.should.equal('09ade30a-f08b-11e7-8c3f-9a214cf093ae');
-        pxCtx.vid.should.equal('0290edec-f08b-11e7-8c3f-9a214cf093ae');
-        JSON.stringify(pxCtx.decodedOriginalToken).should.equal('{"a":"c","s":0,"u":"09ade30a-f08b-11e7-8c3f-9a214cf093ae","t":1830515445000,"v":"0290edec-f08b-11e7-8c3f-9a214cf093ae"}');
-        done();
-    })
-    it('token v3 - should set originalTokenError to decryption_failed on original token decryption fail', (done) => {
-        const pxCtx = {
-            cookies:{
-                _px3:'aaaa'
-            },
-            originalToken: 'aaaaa:bbbbb:cccc:ddddd'
-        }
-
-        originalTokenValidator.evalCookie(pxCtx, config);
-        pxCtx.originalTokenError.should.equal('decryption_failed');
-        done();
-    })
-    it('token v3 - should set originalTokenError to validation_failed on original token validation fail', (done) => {
-        const pxCtx = {
-            cookies:{
-                _px3:'aaaa'
-            },
-            originalToken: '68a1bf96ab3af2e0683a377d332b125dda3e195ee56cf3ce4d61b99cd0860dc:xTMRZvJnzxM=:1000:0pjajaPCjssb2HjG2436zyFXIvIEbE87nFBrHEQPDRT7fqiQ5RA05+njsLUVpOtdJjLvWNNAlSG70DW2wqWM5VmF9UR420/wxPkx6Ebyz/L9q7Mxk5fcdF8p+dGcMc3uD7Qh8y3WiPSN389cXhfKfMttUABQYvRpOxo7rMC+ngpHEVYg+lfBZCliHB1PZKLy'
-        }
-
-        originalTokenValidator.evalCookie(pxCtx, config);
-        pxCtx.originalUuid.should.equal('09ade30a-f08b-11e7-8c3f-9a214cf093ae');
-        pxCtx.vid.should.equal('0290edec-f08b-11e7-8c3f-9a214cf093ae');
-        pxCtx.originalTokenError.should.equal('validation_failed');
-        done();
-    })
-    it('token v1 - should add originalUuid, vid and decodedOriginalToken to pxCtx when original token decryption succeeds', (done) => {
-        const pxCtx = {
-            cookies:{
-                _px:'aaaa'
-            },
-            originalToken: 'Gy9z3mQPYNE=:1000:I7A44BXmO5IlgqhXLM5Mmuq4/jESNgse51Zj/l4bpkAaymDQzcrUMHBofVQ8Q9IYfon3bVQn7gHA124xunjlSlPMlj133wuFBzt7r/yJKpcTEex5WBxynCQAXXx8tymeO1gWXLmPchrV93ysxPl/AeV2/ofVN3YzUR/0PQbXB2fzxkPc5bMPdxLMJCrgLtR4msoMGvg9qaiufMFDWWzah1kvUq1Kvrlk3UQm0y6UU1j6GoLHkTSnDBTg3GexETotOoUkM5FYMPZm8TxK0as+mg=='
-        }
-
-        originalTokenValidator.evalCookie(pxCtx, config);
-        pxCtx.originalUuid.should.equal('09ade30a-f08b-11e7-8c3f-9a214cf093ae');
-        pxCtx.vid.should.equal('0290edec-f08b-11e7-8c3f-9a214cf093ae');
-        JSON.stringify(pxCtx.decodedOriginalToken).should.equal('{"h":"aa2341380b7c67ee0ed5c2f7d4facf03847d7dcb4540aab021654361d3dcade4","s":{"a":0,"b":0},"u":"09ade30a-f08b-11e7-8c3f-9a214cf093ae","t":1830515445000,"v":"0290edec-f08b-11e7-8c3f-9a214cf093ae"}');
-        done();
-    })
-    it('token v1 - should set originalTokenError to decryption_failed on original token decryption fail', (done) => {
-        const pxCtx = {
-            cookies:{
-                _px:'aaaa'
-            },
-            originalToken: 'aaaaa:bbbbb:cccc:ddddd'
-        }
-
-        originalTokenValidator.evalCookie(pxCtx, config);
-        pxCtx.originalTokenError.should.equal('decryption_failed');
-        done();
-    })
-    it('should fail with exception and set originalTokenError to decryption_failed', (done) => {
-        const pxCtx = {
-            cookies: {
-                _px: 'aaaaa'
-            },
-            originalToken:''
-        };
-
-        originalTokenValidator.evalCookie(pxCtx, config);
-        pxCtx.originalTokenError.should.equal('decryption_failed');
-        done();
-    })
-});
-
-describe('PX Enforcer - pxenforcer.js', () => {
-    let params, enforcer, req, stub;
-    beforeEach(() => {
-        params = {
-            pxAppId: 'PX_APP_ID',
-            cookieSecretKey: 'kabum',
-            authToken: 'PX_AUTH_TOKEN',
-            sendPageActivities: true,
-            blockingScore: 60,
-            debugMode: true,
-            ipHeader: 'x-px-true-ip',
-            maxBufferLength: 1,
-            enableModule: true,
-            moduleMode: 1,
-            firstPartyEnabled: true
-        };
-
-        req = {};
-        req.headers = {};
-        req.cookies = {};
-
-        req.originalUrl = "/";
-        req.path = req.originalUrl.substring(req.originalUrl.lastIndexOf('/'));
-        req.protocol = 'http';
-        req.ip = '1.2.3.4';
-        req.hostname = 'example.com'
-        req.get = (key) => {
-            return req.headers[key] || '';
-        };
-
-        stub = sinon.stub(pxhttpc, 'callServer').callsFake((data, headers, uri, callType, ignore, callback) => {
-            return callback ? callback(data) : '';
-        });
-    });
-
-    afterEach(() => {
-        stub.restore();
-    });
-
-    it ('enforces a call in a disabled module', (done) => {
-        params.enableModule = false;
-        enforcer = new PxEnforcer(params, new PxClient());
-        enforcer.enforce(req, null, (response) => {
-
-            (response === undefined).should.equal(true);
-            done();
-        });
-    });
-
-    it ('enforces a call in an enabled module', (done) => {
-        enforcer = new PxEnforcer(params, new PxClient());
-        enforcer.enforce(req, null, (response) => {
-
-            (response === undefined).should.equal(true);
-            done();
-        });
-    });
-    it('uses first party to get client', (done) => {
-        let reqStub = sinon.stub(request, 'get').callsFake((data, callback) => {
-            callback(null, {headers: {'x-px-johnny': '1'}, body:"hello buddy"});
-        })
-        req.originalUrl = "/_APP_ID/init.js";
-        enforcer = new PxEnforcer(params, new PxClient());
-        enforcer.enforce(req, null, (error, response) => {
-            (response === undefined).should.equal(false);
-            response.body.should.equal("hello buddy");
-            response.headers['x-px-johnny'].should.equal('1')
-            reqStub.restore();
-            done();
-        });
-    });
-    it('uses first party for xhr post request', (done) => {
-        let reqStub = sinon.stub(request, 'post').callsFake((data, callback) => {
-            callback(null, {headers: {'x-px-johnny': '1'}, body:"hello buddy"});
-        })
-        req.originalUrl = "/_APP_ID/xhr/something";
-        req.method = "POST";
-        req.body = "test";
-        enforcer = new PxEnforcer(params, new PxClient());
-        enforcer.enforce(req, null, (error, response) => {
-            (response === undefined).should.equal(false);
-            response.body.should.equal("hello buddy");
-            response.headers['x-px-johnny'].should.equal('1')
-            reqStub.restore();
-            done();
-        });
-    });
-    it('uses first party for xhr get request', (done) => {
-        let reqStub = sinon.stub(request, 'get').callsFake((data, callback) => {
-            callback(null, {headers: {'x-px-johnny': '1'}, body:"hello buddy"});
-        })
-        req.originalUrl = "/_APP_ID/xhr/something";
-        req.method = "GET";
-        req.body = "test";
-        enforcer = new PxEnforcer(params, new PxClient());
-        enforcer.enforce(req, null, (error, response) => {
-            (response === undefined).should.equal(false);
-            response.body.should.equal("hello buddy");
-            response.headers['x-px-johnny'].should.equal('1')
-            reqStub.restore();
-            done();
-        });
-    });
-    it ('uses first party with pxvid cookie', (done) => {
-        let reqStub = sinon.stub(request, 'post').callsFake((data, callback) => {
-            callback(null, {headers: {'x-px-johnny': '1'}, body:"hello buddy"});
-        })
-        req.originalUrl = "/_APP_ID/xhr/something";
-        req.method = "POST";
-        req.cookies['_pxvid'] = "abab-123";
-        req.body = "test";
-        enforcer = new PxEnforcer(params, new PxClient());
-        enforcer.enforce(req, null, (error, response) => {
-            (response === undefined).should.equal(false);
-            response.body.should.equal("hello buddy");
-            response.headers['x-px-johnny'].should.equal('1')
-            reqStub.restore();
-            done();
-        });
-    })
-    it('uses first party for xhr and passed trough bodyParser', (done) => {
-        let reqStub = sinon.stub(request, 'post').callsFake((data, callback) => {
-            callback(null, {headers: {'x-px-johnny': '1'}, body:"hello buddy"});
-        })
-        req.originalUrl = "/_APP_ID/xhr/something";
-        req.method = "POST";
-        req.body={key: 'value', anotherKey:'anotherValue'};
-        enforcer = new PxEnforcer(params, new PxClient());
-        enforcer.enforce(req, null, (error, response) => {
-            (response === undefined).should.equal(false);
-            response.body.should.equal("hello buddy");
-            response.headers['x-px-johnny'].should.equal('1')
-            reqStub.restore();
-            done();
-        });
-    })
-    it('uses upper case for xhr', (done) => {
-        let reqStub = sinon.stub(request, 'post').callsFake((data, callback) => {
-            callback(null, {headers: {'x-px-johnny': '1'}, body:"hello buddy"});
-        })
-        req.originalUrl = "/_APP_ID/XHR/something";
-        req.method = "POST";
-        req.body={key: 'value', anotherKey:'anotherValue'};
-        enforcer = new PxEnforcer(params, new PxClient());
-        enforcer.enforce(req, null, (error, response) => {
-            (response === undefined).should.equal(false);
-            response.body.should.equal("hello buddy");
-            response.headers['x-px-johnny'].should.equal('1')
-            reqStub.restore();
-            done();
-        });
-    })
-});
-
-

From 3e3380bef8750b19aeae35d8b796054b32bb45c3 Mon Sep 17 00:00:00 2001
From: Johnny Tordgeman <johnny@perimeterx.com>
Date: Mon, 30 Jul 2018 16:11:55 +0300
Subject: [PATCH 2/9] Version 1.4.2

---
 CHANGELOG.md | 4 ++++
 README.md    | 2 +-
 package.json | 2 +-
 3 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c6781e6b..ef5caab7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](http://keepachangelog.com/)
 and this project adheres to [Semantic Versioning](http://semver.org/).
 
+## [1.4.2] - 2018-07-30
+### Fixed
+- phin callback related issue
+
 ## [1.4.1] - 2018-07-29
 ### Fixed
 - Various fixes regarding page_requested and pass_reason
diff --git a/README.md b/README.md
index fd405342..f0d4fa07 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
 [PerimeterX](http://www.perimeterx.com) Shared base for NodeJS enforcers
 =============================================================
 
-> Latest stable version: [v1.4.1](https://www.npmjs.com/package/perimeterx-node-core)
+> Latest stable version: [v1.4.2](https://www.npmjs.com/package/perimeterx-node-core)
 
 This is a shared base implementation for PerimeterX Express enforcer and future NodeJS enforcers. For a fully functioning implementation example, see the [Node-Express enforcer](https://github.com/PerimeterX/perimeterx-node-express/) implementation.
 
diff --git a/package.json b/package.json
index 20cc8b13..cc4b2c59 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "perimeterx-node-core",
-  "version": "1.4.1",
+  "version": "1.4.2",
   "description": "PerimeterX NodeJS shared core for various applications to monitor and block traffic according to PerimeterX risk score",
   "main": "index.js",
   "scripts": {

From 59eb90faee8c7d1978750514916f745b2654c9d0 Mon Sep 17 00:00:00 2001
From: Johnny Tordgeman <johnny@perimeterx.com>
Date: Tue, 31 Jul 2018 13:20:46 +0300
Subject: [PATCH 3/9] refactored the use of pxblock and pxpass (#60)

---
 lib/pxenforcer.js | 100 ++++++++++++++++++++++++----------------------
 1 file changed, 52 insertions(+), 48 deletions(-)

diff --git a/lib/pxenforcer.js b/lib/pxenforcer.js
index f648ca3a..9959dbf1 100644
--- a/lib/pxenforcer.js
+++ b/lib/pxenforcer.js
@@ -133,6 +133,15 @@ class PxEnforcer {
 
 
     handleVerification(pxCtx, pxConfig, req, res, cb) {
+        const verified = pxCtx.score < pxConfig.BLOCKING_SCORE;
+
+        // Handle async activities
+        if (verified) {
+            this.pxPass(pxCtx);
+        } else {
+            this.pxBlock(pxCtx, pxConfig);
+        }
+
         // check for additional activity handler
         if (pxConfig.ADDITIONAL_ACTIVITY_HANDLER) {
             pxConfig.ADDITIONAL_ACTIVITY_HANDLER(pxCtx, pxConfig);
@@ -150,63 +159,58 @@ class PxEnforcer {
                     return cb(null, result);
                 }
             }
-
         }
-        if (pxCtx.score < pxConfig.BLOCKING_SCORE) {
-            this.pxPass(pxCtx);
+
+         // If verified, pass the request here
+        if (verified || pxConfig.MODULE_MODE === pxConfig.MONITOR_MODE.MONITOR) {
             return cb();
-        } else {
-            this.pxBlock(pxCtx, pxConfig);
-            if (pxConfig.MODULE_MODE === pxConfig.MONITOR_MODE.MONITOR) {
-                return cb();
-            }
+        }
 
-            const acceptHeaderValue = req.headers["accept"] || req.headers["content-type"];
-            const isJsonResponse = acceptHeaderValue && acceptHeaderValue.split(',').find((value) => value.toLowerCase() === "application/json") && pxCtx.cookieOrigin === "cookie" && pxCtx.blockAction !== 'r';
+        const acceptHeaderValue = req.headers["accept"] || req.headers["content-type"];
+        const isJsonResponse = acceptHeaderValue && acceptHeaderValue.split(',').find((value) => value.toLowerCase() === "application/json") && pxCtx.cookieOrigin === "cookie" && pxCtx.blockAction !== 'r';
 
-            pxLogger.debug(`Enforcing action:  ${pxUtil.parseAction(pxCtx.blockAction)} page is served ${isJsonResponse ? "using advanced protection mode" : ""}`);
-            this.generateResponse(pxCtx, pxConfig, isJsonResponse, function (responseObject) {
-                const response = {
-                    status: '403',
-                    statusDescription: "Forbidden"
-                };
+        pxLogger.debug(`Enforcing action:  ${pxUtil.parseAction(pxCtx.blockAction)} page is served ${isJsonResponse ? "using advanced protection mode" : ""}`);
+        this.generateResponse(pxCtx, pxConfig, isJsonResponse, function (responseObject) {
+            const response = {
+                status: '403',
+                statusDescription: "Forbidden"
+            };
 
-                if (pxCtx.blockAction === 'r') {
-                    response.status = '429';
-                    response.statusDescription = "Too Many Requests";
-                }
+            if (pxCtx.blockAction === 'r') {
+                response.status = '429';
+                response.statusDescription = "Too Many Requests";
+            }
 
-                if (isJsonResponse) {
-                    response.header = {key: 'Content-Type', value: 'application/json'};
-                    response.body = {
-                        appId: responseObject.appId,
-                        jsClientSrc: responseObject.jsClientSrc,
-                        firstPartyEnabled: responseObject.firstPartyEnabled,
-                        vid: responseObject.vid,
-                        uuid: responseObject.uuid,
-                        hostUrl: responseObject.hostUrl,
-                        blockScript: responseObject.blockScript
-                    }
-                    return cb(null, response);
+            if (isJsonResponse) {
+                response.header = {key: 'Content-Type', value: 'application/json'};
+                response.body = {
+                    appId: responseObject.appId,
+                    jsClientSrc: responseObject.jsClientSrc,
+                    firstPartyEnabled: responseObject.firstPartyEnabled,
+                    vid: responseObject.vid,
+                    uuid: responseObject.uuid,
+                    hostUrl: responseObject.hostUrl,
+                    blockScript: responseObject.blockScript
                 }
+                return cb(null, response);
+            }
 
-                response.header = {key: 'Content-Type', value: 'text/html'};
-                response.body = responseObject;
-
-                if (pxCtx.cookieOrigin !== "cookie") {
-                    response.header = {key: 'Content-Type', value: 'application/json'};
-                    response.body = {
-                        action: pxUtil.parseAction(pxCtx.blockAction),
-                        uuid: pxCtx.uuid,
-                        vid: pxCtx.vid,
-                        appId: pxConfig.PX_APP_ID,
-                        page: new Buffer(responseObject).toString('base64'),
-                        collectorUrl: pxCtx.collectorUrl
-                    }
+            response.header = {key: 'Content-Type', value: 'text/html'};
+            response.body = responseObject;
+
+            if (pxCtx.cookieOrigin !== "cookie") {
+                response.header = {key: 'Content-Type', value: 'application/json'};
+                response.body = {
+                    action: pxUtil.parseAction(pxCtx.blockAction),
+                    uuid: pxCtx.uuid,
+                    vid: pxCtx.vid,
+                    appId: pxConfig.PX_APP_ID,
+                    page: new Buffer(responseObject).toString('base64'),
+                    collectorUrl: pxCtx.collectorUrl
                 }
-                cb(null, response);
-            });
-        }
+            }
+            cb(null, response);
+        });
     }
 
     get config() {

From ce55b0353f8b7c3222b983b9ae06c41d7eb8c286 Mon Sep 17 00:00:00 2001
From: Johnny Tordgeman <johnny@perimeterx.com>
Date: Tue, 31 Jul 2018 17:20:27 +0300
Subject: [PATCH 4/9] updated changelog

---
 CHANGELOG.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ef5caab7..e9d45d87 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 ## [1.4.2] - 2018-07-30
 ### Fixed
 - phin callback related issue
+- no activities get sent if customRequestHandler is used
 
 ## [1.4.1] - 2018-07-29
 ### Fixed

From c4d998fd938ee5b51279d19bb615bd9a3d0607f7 Mon Sep 17 00:00:00 2001
From: Alex Bluvstein <alex.bluvstein@perimeterx.com>
Date: Thu, 2 Aug 2018 15:17:54 +0300
Subject: [PATCH 5/9] APP-945

Fixed parsing of original token, removing prefix before parsing
---
 lib/pxoriginaltoken.js | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/lib/pxoriginaltoken.js b/lib/pxoriginaltoken.js
index 92f96f04..04244d16 100644
--- a/lib/pxoriginaltoken.js
+++ b/lib/pxoriginaltoken.js
@@ -2,9 +2,11 @@ const TokenV3 = require('./cookie/tokenV3');
 const TokenV1 = require('./cookie/tokenV1');
 const pxLogger = require('./pxlogger');
 
-function evalCookie(pxCtx, pxConfig) {
+function evalCookie(pxCtx, pxConfig, delimiter = ":") {
     try {
-        const cookie = (pxCtx.cookies['_px3'] ? new TokenV3(pxCtx, pxConfig, pxCtx.originalToken) : new TokenV1(pxCtx, pxConfig, pxCtx.originalToken))
+        let [version, ...extractedCookie] = pxCtx.originalToken.split(delimiter);
+        let noVersionOriginalToken = extractedCookie.join(delimiter);
+        const cookie = (pxCtx.cookies['_px3'] ? new TokenV3(pxCtx, pxConfig, noVersionOriginalToken) : new TokenV1(pxCtx, pxConfig, noVersionOriginalToken))
         pxLogger.debug('Original token found, Evaluating');
 
         if (!cookie.deserialize()) {

From f40cfec03db0d4e879ab589b6455e68b3a6693ef Mon Sep 17 00:00:00 2001
From: Alex Bluvstein <alex.bluvstein@perimeterx.com>
Date: Thu, 2 Aug 2018 16:29:49 +0300
Subject: [PATCH 6/9] Revert "APP-945"

This reverts commit c4d998fd938ee5b51279d19bb615bd9a3d0607f7.

 Changes to be committed:
	modified:   lib/pxoriginaltoken.js

Reverting a commit made by mistake
---
 lib/pxoriginaltoken.js | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/lib/pxoriginaltoken.js b/lib/pxoriginaltoken.js
index 04244d16..92f96f04 100644
--- a/lib/pxoriginaltoken.js
+++ b/lib/pxoriginaltoken.js
@@ -2,11 +2,9 @@ const TokenV3 = require('./cookie/tokenV3');
 const TokenV1 = require('./cookie/tokenV1');
 const pxLogger = require('./pxlogger');
 
-function evalCookie(pxCtx, pxConfig, delimiter = ":") {
+function evalCookie(pxCtx, pxConfig) {
     try {
-        let [version, ...extractedCookie] = pxCtx.originalToken.split(delimiter);
-        let noVersionOriginalToken = extractedCookie.join(delimiter);
-        const cookie = (pxCtx.cookies['_px3'] ? new TokenV3(pxCtx, pxConfig, noVersionOriginalToken) : new TokenV1(pxCtx, pxConfig, noVersionOriginalToken))
+        const cookie = (pxCtx.cookies['_px3'] ? new TokenV3(pxCtx, pxConfig, pxCtx.originalToken) : new TokenV1(pxCtx, pxConfig, pxCtx.originalToken))
         pxLogger.debug('Original token found, Evaluating');
 
         if (!cookie.deserialize()) {

From 3106a523bb73c7fa02e4267d8224049be1a27688 Mon Sep 17 00:00:00 2001
From: alexbpx <41577203+alexbpx@users.noreply.github.com>
Date: Thu, 2 Aug 2018 16:33:33 +0300
Subject: [PATCH 7/9] App 945 (#61)

* APP-945 : Fixed parsing of original token, removing prefix before parsing

* APP-945 : Fixed UTs to work with the latest original token parsing method
---
 lib/pxoriginaltoken.js | 6 ++++--
 test/pxapi.test.js     | 6 +++---
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/lib/pxoriginaltoken.js b/lib/pxoriginaltoken.js
index 92f96f04..04244d16 100644
--- a/lib/pxoriginaltoken.js
+++ b/lib/pxoriginaltoken.js
@@ -2,9 +2,11 @@ const TokenV3 = require('./cookie/tokenV3');
 const TokenV1 = require('./cookie/tokenV1');
 const pxLogger = require('./pxlogger');
 
-function evalCookie(pxCtx, pxConfig) {
+function evalCookie(pxCtx, pxConfig, delimiter = ":") {
     try {
-        const cookie = (pxCtx.cookies['_px3'] ? new TokenV3(pxCtx, pxConfig, pxCtx.originalToken) : new TokenV1(pxCtx, pxConfig, pxCtx.originalToken))
+        let [version, ...extractedCookie] = pxCtx.originalToken.split(delimiter);
+        let noVersionOriginalToken = extractedCookie.join(delimiter);
+        const cookie = (pxCtx.cookies['_px3'] ? new TokenV3(pxCtx, pxConfig, noVersionOriginalToken) : new TokenV1(pxCtx, pxConfig, noVersionOriginalToken))
         pxLogger.debug('Original token found, Evaluating');
 
         if (!cookie.deserialize()) {
diff --git a/test/pxapi.test.js b/test/pxapi.test.js
index f17c0436..a9759a54 100644
--- a/test/pxapi.test.js
+++ b/test/pxapi.test.js
@@ -72,7 +72,7 @@ describe('PX API - pxapi.js', () => {
             cookies: {
                 _px3: 'aaaa'
             },
-            originalToken: '68a1bf96ab3af2e0683a377d332b125dda3e195ee56cf3ce4d61b99cd0860dc6:xTMRZvJnzxM=:1000:0pjajaPCjssb2HjG2436zyFXIvIEbE87nFBrHEQPDRT7fqiQ5RA05+njsLUVpOtdJjLvWNNAlSG70DW2wqWM5VmF9UR420/wxPkx6Ebyz/L9q7Mxk5fcdF8p+dGcMc3uD7Qh8y3WiPSN389cXhfKfMttUABQYvRpOxo7rMC+ngpHEVYg+lfBZCliHB1PZKLy'
+            originalToken: '3:68a1bf96ab3af2e0683a377d332b125dda3e195ee56cf3ce4d61b99cd0860dc6:xTMRZvJnzxM=:1000:0pjajaPCjssb2HjG2436zyFXIvIEbE87nFBrHEQPDRT7fqiQ5RA05+njsLUVpOtdJjLvWNNAlSG70DW2wqWM5VmF9UR420/wxPkx6Ebyz/L9q7Mxk5fcdF8p+dGcMc3uD7Qh8y3WiPSN389cXhfKfMttUABQYvRpOxo7rMC+ngpHEVYg+lfBZCliHB1PZKLy'
         };
 
         originalTokenValidator.evalCookie(pxCtx, config);
@@ -98,7 +98,7 @@ describe('PX API - pxapi.js', () => {
             cookies: {
                 _px3: 'aaaa'
             },
-            originalToken: '68a1bf96ab3af2e0683a377d332b125dda3e195ee56cf3ce4d61b99cd0860dc:xTMRZvJnzxM=:1000:0pjajaPCjssb2HjG2436zyFXIvIEbE87nFBrHEQPDRT7fqiQ5RA05+njsLUVpOtdJjLvWNNAlSG70DW2wqWM5VmF9UR420/wxPkx6Ebyz/L9q7Mxk5fcdF8p+dGcMc3uD7Qh8y3WiPSN389cXhfKfMttUABQYvRpOxo7rMC+ngpHEVYg+lfBZCliHB1PZKLy'
+            originalToken: '3:68a1bf96ab3af2e0683a377d332b125dda3e195ee56cf3ce4d61b99cd0860dc:xTMRZvJnzxM=:1000:0pjajaPCjssb2HjG2436zyFXIvIEbE87nFBrHEQPDRT7fqiQ5RA05+njsLUVpOtdJjLvWNNAlSG70DW2wqWM5VmF9UR420/wxPkx6Ebyz/L9q7Mxk5fcdF8p+dGcMc3uD7Qh8y3WiPSN389cXhfKfMttUABQYvRpOxo7rMC+ngpHEVYg+lfBZCliHB1PZKLy'
         };
 
         originalTokenValidator.evalCookie(pxCtx, config);
@@ -112,7 +112,7 @@ describe('PX API - pxapi.js', () => {
             cookies: {
                 _px: 'aaaa'
             },
-            originalToken: 'Gy9z3mQPYNE=:1000:I7A44BXmO5IlgqhXLM5Mmuq4/jESNgse51Zj/l4bpkAaymDQzcrUMHBofVQ8Q9IYfon3bVQn7gHA124xunjlSlPMlj133wuFBzt7r/yJKpcTEex5WBxynCQAXXx8tymeO1gWXLmPchrV93ysxPl/AeV2/ofVN3YzUR/0PQbXB2fzxkPc5bMPdxLMJCrgLtR4msoMGvg9qaiufMFDWWzah1kvUq1Kvrlk3UQm0y6UU1j6GoLHkTSnDBTg3GexETotOoUkM5FYMPZm8TxK0as+mg=='
+            originalToken: '3:Gy9z3mQPYNE=:1000:I7A44BXmO5IlgqhXLM5Mmuq4/jESNgse51Zj/l4bpkAaymDQzcrUMHBofVQ8Q9IYfon3bVQn7gHA124xunjlSlPMlj133wuFBzt7r/yJKpcTEex5WBxynCQAXXx8tymeO1gWXLmPchrV93ysxPl/AeV2/ofVN3YzUR/0PQbXB2fzxkPc5bMPdxLMJCrgLtR4msoMGvg9qaiufMFDWWzah1kvUq1Kvrlk3UQm0y6UU1j6GoLHkTSnDBTg3GexETotOoUkM5FYMPZm8TxK0as+mg=='
         };
 
         originalTokenValidator.evalCookie(pxCtx, config);

From c345318801b7e4e529e36e42b4f0ca4217cac2b1 Mon Sep 17 00:00:00 2001
From: Johnny Tordgeman <johnny@perimeterx.com>
Date: Thu, 9 Aug 2018 16:33:08 +0300
Subject: [PATCH 8/9] Refactored timeout error handling

---
 lib/pxapi.js    | 2 ++
 lib/pxconfig.js | 4 +++-
 lib/pxhttpc.js  | 4 ++--
 3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/lib/pxapi.js b/lib/pxapi.js
index c8ad9731..b48a2341 100644
--- a/lib/pxapi.js
+++ b/lib/pxapi.js
@@ -124,6 +124,7 @@ function evalByServerCall(pxCtx, callback) {
                 return callback(config.SCORE_EVALUATE_ACTION.S2S_TIMEOUT_PASS);
             }
             pxLogger.error(`Unexpected exception while evaluating Risk cookie. ${err}`);
+            pxCtx.passReason = pxConfig.conf.PASS_REASON.REQUEST_FAILED;
             return callback(config.SCORE_EVALUATE_ACTION.UNEXPECTED_RESULT);
         }
         let action = isBadRiskScore(res, pxCtx);
@@ -163,6 +164,7 @@ function evalByServerCall(pxCtx, callback) {
  */
 function isBadRiskScore(res, pxCtx) {
     if (!res || !pxUtil.verifyDefined(res.score) || !res.action) {
+        pxCtx.passReason = pxConfig.conf.PASS_REASON.INVALID_RESPONSE;
         return -1;
     }
     let score = res.score;
diff --git a/lib/pxconfig.js b/lib/pxconfig.js
index 108d4e5b..7e26de6d 100644
--- a/lib/pxconfig.js
+++ b/lib/pxconfig.js
@@ -65,7 +65,9 @@ PX_INTERNAL.PASS_REASON = {
     COOKIE: "cookie",
     S2S: "s2s",
     S2S_TIMEOUT: "s2s_timeout",
-    MONITOR_MODE: "monitor_mode"
+    MONITOR_MODE: "monitor_mode",
+    INVALID_RESPONSE: "invalid_response",
+    REQUEST_FAILED: "request_failed"
 }
 
 PX_INTERNAL.MONITOR_MODE = {
diff --git a/lib/pxhttpc.js b/lib/pxhttpc.js
index e7920282..2de99973 100644
--- a/lib/pxhttpc.js
+++ b/lib/pxhttpc.js
@@ -31,10 +31,10 @@ function callServer(data, headers, uri, callType, callback) {
         request.post(callData, function (err, response) {
             let data;
             if (err) {
-                if (err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT' || err.code === 'ECONNRESET') {
+                if (err == "Error: Timeout has been reached.") {
                     return callback('timeout');
                 } else {
-                    return callback('perimeterx server did not return a valid response');
+                    return callback(`perimeterx server did not return a valid response. Error: ${err}`);
                 }
             }
             if (typeof(response.body) !== "undefined" && response.body !== null) {

From 78c597b2e4e0739001aa6c1e7e4db89798d2a43c Mon Sep 17 00:00:00 2001
From: Johnny Tordgeman <johnny@perimeterx.com>
Date: Thu, 9 Aug 2018 17:45:09 +0300
Subject: [PATCH 9/9] Update CHANGELOG.md

---
 CHANGELOG.md | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e9d45d87..2bf8db8e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,8 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 
 ## [1.4.2] - 2018-07-30
 ### Fixed
-- phin callback related issue
-- no activities get sent if customRequestHandler is used
+- Phin callback related issue
+- Better handling of activities when customRequestHandler is used
+- Better error messages for requests
 
 ## [1.4.1] - 2018-07-29
 ### Fixed
