From 4eaa436a9977ab8799bafe87cf7a4d1d9807690e Mon Sep 17 00:00:00 2001 From: Hernanfaifman Date: Mon, 1 Apr 2024 12:56:13 -0300 Subject: [PATCH 1/2] Added enforcement of https for service client url --- spec/src/constructorio.js | 23 ++++++++++++++++++++++- spec/src/utils/helpers.js | 29 +++++++++++++++++++++++++++++ src/constructorio.js | 4 +++- src/utils/helpers.js | 21 +++++++++++++++++++++ 4 files changed, 75 insertions(+), 2 deletions(-) diff --git a/spec/src/constructorio.js b/spec/src/constructorio.js index 29671868..b386e8c5 100644 --- a/spec/src/constructorio.js +++ b/spec/src/constructorio.js @@ -58,7 +58,7 @@ describe(`ConstructorIO${bundledDescriptionSuffix}`, () => { it('Should return an instance with custom options when valid API key is provided', () => { const clientId = 'client-id'; const sessionId = 'session-id'; - const serviceUrl = 'http://constructor.io'; + const serviceUrl = 'https://constructor.io'; const quizzesServiceUrl = 'http://quizzes.constructor.io'; const version = 'custom-version'; const networkParameters = { timeout: 5000 }; @@ -81,6 +81,27 @@ describe(`ConstructorIO${bundledDescriptionSuffix}`, () => { expect(instance.options).to.have.property('networkParameters').to.equal(networkParameters); }); + it('Should return an instance with correct serviceUrl when a http serviceUrl is passed', () => { + const clientId = 'client-id'; + const sessionId = 'session-id'; + const serviceUrl = 'https://constructor.io'; + const quizzesServiceUrl = 'http://quizzes.constructor.io'; + const version = 'custom-version'; + const networkParameters = { timeout: 5000 }; + const instance = new ConstructorIO({ + apiKey: validApiKey, + clientId, + sessionId, + serviceUrl, + quizzesServiceUrl, + version, + networkParameters, + }); + + expect(instance).to.be.an('object'); + expect(instance.options).to.have.property('serviceUrl').to.equal('https://constructor.io'); + }); + it('Should remove any trailing slashes from the serviceUrl', () => { const serviceUrl = 'https://constructor.io/'; const instance = new ConstructorIO({ diff --git a/spec/src/utils/helpers.js b/spec/src/utils/helpers.js index e17dad6b..9170968c 100644 --- a/spec/src/utils/helpers.js +++ b/spec/src/utils/helpers.js @@ -20,6 +20,7 @@ const { addOrderIdRecord, applyNetworkTimeout, stringify, + addHTTPSToString, } = require('../../../test/utils/helpers'); // eslint-disable-line import/extensions const jsdom = require('./jsdom-global'); const store = require('../../../test/utils/store'); // eslint-disable-line import/extensions @@ -402,5 +403,33 @@ describe('ConstructorIO - Utils - Helpers', () => { expect(stringified).to.equal('a=1&b=1%2C2&c=2&c=3&d=true&d=false&e%5Bf%5D=g&e%5Bf%5D=h'); }); }); + + describe('addHTTPSToString', () => { + it('Should return the url without any modification', () => { + const testUrl = 'https://www.constructor.io'; + + expect(addHTTPSToString(testUrl)).to.equal(testUrl); + }); + + it('Should return url with no protocol with https at the beginning', () => { + const testUrl = 'www.constructor.io'; + const expectedUrl = 'https://www.constructor.io'; + + expect(addHTTPSToString(testUrl)).to.equal(expectedUrl); + }); + + it('Should return url with an http protocol with https at the beginning', () => { + const testUrl = 'http://www.constructor.io'; + const expectedUrl = 'https://www.constructor.io'; + + expect(addHTTPSToString(testUrl)).to.equal(expectedUrl); + }); + + it('Should return null if param is not a string', () => { + const testUrl = {}; + + expect(addHTTPSToString(testUrl)).to.equal(null); + }); + }); } }); diff --git a/src/constructorio.js b/src/constructorio.js index 1860bf25..9981a7bf 100644 --- a/src/constructorio.js +++ b/src/constructorio.js @@ -105,10 +105,12 @@ class ConstructorIO { } } + const normalizedServiceUrl = serviceUrl && serviceUrl.replace(/\/$/, ''); + this.options = { apiKey, version: versionFromOptions || versionFromGlobal || computePackageVersion(), - serviceUrl: (serviceUrl && serviceUrl.replace(/\/$/, '')) || 'https://ac.cnstrc.com', + serviceUrl: helpers.addHTTPSToString(normalizedServiceUrl) || 'https://ac.cnstrc.com', quizzesServiceUrl: (quizzesServiceUrl && quizzesServiceUrl.replace(/\/$/, '')) || 'https://quizzes.cnstrc.com', sessionId: sessionId || session_id, clientId: clientId || client_id, diff --git a/src/utils/helpers.js b/src/utils/helpers.js index bad06a5b..ceb68044 100644 --- a/src/utils/helpers.js +++ b/src/utils/helpers.js @@ -238,6 +238,27 @@ const utils = { return obfuscatedUrl; }, + + addHTTPSToString(url) { + if (typeof url !== 'string') { + return null; + } + + const doesUrlIncludeHTTPS = url.startsWith('https://'); + const doesUrlStartWithHTTP = url.startsWith('http://'); + + if (!doesUrlIncludeHTTPS && doesUrlStartWithHTTP) { + return url.replace('http', 'https'); + } + + if (!doesUrlStartWithHTTP && !doesUrlIncludeHTTPS) { + const urlWithHttps = `https://${url}`; + + return urlWithHttps; + } + + return url; + }, }; module.exports = utils; From 75b91986a5ebb8c00246c59a72d4044a99e95d54 Mon Sep 17 00:00:00 2001 From: Hernan Faifman Date: Tue, 2 Apr 2024 16:25:02 -0300 Subject: [PATCH 2/2] updated test --- spec/src/constructorio.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/spec/src/constructorio.js b/spec/src/constructorio.js index b386e8c5..b332f513 100644 --- a/spec/src/constructorio.js +++ b/spec/src/constructorio.js @@ -84,18 +84,12 @@ describe(`ConstructorIO${bundledDescriptionSuffix}`, () => { it('Should return an instance with correct serviceUrl when a http serviceUrl is passed', () => { const clientId = 'client-id'; const sessionId = 'session-id'; - const serviceUrl = 'https://constructor.io'; - const quizzesServiceUrl = 'http://quizzes.constructor.io'; - const version = 'custom-version'; - const networkParameters = { timeout: 5000 }; + const serviceUrl = 'http://constructor.io'; const instance = new ConstructorIO({ apiKey: validApiKey, clientId, sessionId, serviceUrl, - quizzesServiceUrl, - version, - networkParameters, }); expect(instance).to.be.an('object');