Skip to content

Commit

Permalink
feat(FEC-9545): add ability to correlate udrm calls to player type an…
Browse files Browse the repository at this point in the history
…d session (#297)

In addKalturaParams, if a source has udrm licenseurl then append sessionid, clienttag, referrer and uiConfId as query params.
  • Loading branch information
RoyBregman authored Jan 29, 2020
1 parent d95ef8c commit c7f7748
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 35 deletions.
88 changes: 64 additions & 24 deletions src/common/utils/kaltura-params.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ import {StreamType, Utils} from '@playkit-js/playkit-js';

const PLAY_MANIFEST = 'playmanifest/';
const PLAY_SESSION_ID = 'playSessionId=';
const DRM_SESSION_ID = 'sessionId=';
const REFERRER = 'referrer=';
const UICONF_ID = 'uiConfId=';
const CLIENT_TAG = 'clientTag=html5:v';
const UDRM_DOMAIN = 'kaltura.com';
const CUSTOM_DATA = 'custom_data=';
const SIGNATURE = 'signature=';

/**
* @param {Player} player - player
Expand Down Expand Up @@ -59,23 +64,24 @@ function setSessionId(playerConfig: PartialKPOptionsObject, sessionId: string):
}

/**
* @param {PKMediaSourceObject} source - PKMediaSourceObject
* @param {string} url - url
* @param {string} sessionId - session id
* @return {void}
* @param {string} paramName - optional param name of the session id
* @return {string} - the url with the new sessionId
* @private
*/
function updateSessionIdInUrl(source: Object = {}, sessionId: ?string): void {
function updateSessionIdInUrl(url: string, sessionId: ?string, paramName: string = PLAY_SESSION_ID): string {
if (sessionId) {
let sessionIdInUrlRegex = new RegExp(PLAY_SESSION_ID + '((?:[a-z0-9]|-)*:(?:[a-z0-9]|-)*)', 'i');
let sessionIdInUrl = sessionIdInUrlRegex.exec(source.url);
let sessionIdInUrlRegex = new RegExp(paramName + '((?:[a-z0-9]|-)*:(?:[a-z0-9]|-)*)', 'i');
let sessionIdInUrl = sessionIdInUrlRegex.exec(url);
if (sessionIdInUrl && sessionIdInUrl[1]) {
// this url has session id (has already been played)
source.url = source.url.replace(sessionIdInUrl[1], sessionId);
url = url.replace(sessionIdInUrl[1], sessionId);
} else {
let delimiter = source.url.indexOf('?') === -1 ? '?' : '&';
source.url += delimiter + PLAY_SESSION_ID + sessionId;
url += getQueryStringParamDelimiter(url) + paramName + sessionId;
}
}
return url;
}

/**
Expand All @@ -94,28 +100,51 @@ function getReferrer(): string {
}

/**
* @param {PKMediaSourceObject} source - source
* @return {void}
* @param {string} url - url
* @return {string} - the url with the referrer appended in the query params
* @private
*/
function addReferrer(source: PKMediaSourceObject): void {
if (source.url.indexOf(REFERRER) === -1) {
let delimiter = source.url.indexOf('?') === -1 ? '?' : '&';
function addReferrer(url: string): string {
if (url.indexOf(REFERRER) === -1) {
let referrer = btoa(getReferrer().substr(0, 1000));
source.url += delimiter + REFERRER + referrer;
url += getQueryStringParamDelimiter(url) + REFERRER + referrer;
}
return url;
}

/**
* @param {PKMediaSourceObject} source - source
* @return {void}
* @param {string} url - url
* @param {PartialKPOptionsObject} playerConfig - player config
* @return {string} - the url with the uiconf id appended in the query params
* @private
*/
function addUIConfId(url: string, playerConfig: PartialKPOptionsObject): string {
const uiConfId = Utils.Object.getPropertyPath(playerConfig, 'provider.uiConfId');
if (url.indexOf(UICONF_ID) === -1 && typeof uiConfId === 'number') {
url += getQueryStringParamDelimiter(url) + UICONF_ID + uiConfId;
}
return url;
}

/**
* @param {string} url - url
* @return {string} - returns the next param delimiter (? or &) according to the current url structure
* @private
*/
function getQueryStringParamDelimiter(url: string): string {
return url.indexOf('?') === -1 ? '?' : '&';
}

/**
* @param {string} url - url
* @return {string} - the url with the client tag appended in the query params
* @private
*/
function addClientTag(source: PKMediaSourceObject): void {
if (source.url.indexOf(CLIENT_TAG) === -1) {
let delimiter = source.url.indexOf('?') === -1 ? '?' : '&';
source.url += delimiter + CLIENT_TAG + __VERSION__;
function addClientTag(url: string): string {
if (url.indexOf(CLIENT_TAG) === -1) {
url += getQueryStringParamDelimiter(url) + CLIENT_TAG + __VERSION__;
}
return url;
}

/**
Expand All @@ -128,18 +157,29 @@ function addClientTag(source: PKMediaSourceObject): void {
function addKalturaParams(player: Player, playerConfig: PartialKPOptionsObject): void {
handleSessionId(player, playerConfig);
const sources = playerConfig.sources;
const sessionId = playerConfig.session && playerConfig.session.id;
Object.values(StreamType).forEach(key => {
// $FlowFixMe
if (sources[key]) {
sources[key].forEach(source => {
if (typeof source.url === 'string' && source.url.toLowerCase().indexOf(PLAY_MANIFEST) > -1 && !source.localSource) {
updateSessionIdInUrl(source, playerConfig.session && playerConfig.session.id);
addReferrer(source);
addClientTag(source);
source.url = updateSessionIdInUrl(source.url, sessionId);
source.url = addReferrer(source.url);
source.url = addClientTag(source.url);
}
if (source.drmData && source.drmData.length) {
source.drmData.forEach(drmData => {
if (typeof drmData.licenseUrl === 'string' && [UDRM_DOMAIN, CUSTOM_DATA, SIGNATURE].every(t => drmData.licenseUrl.includes(t))) {
drmData.licenseUrl = updateSessionIdInUrl(drmData.licenseUrl, sessionId, DRM_SESSION_ID);
drmData.licenseUrl = addClientTag(drmData.licenseUrl);
drmData.licenseUrl = addReferrer(drmData.licenseUrl);
drmData.licenseUrl = addUIConfId(drmData.licenseUrl, playerConfig);
}
});
}
});
}
});
}

export {addKalturaParams, handleSessionId, updateSessionIdInUrl, getReferrer, addReferrer, addClientTag};
export {addKalturaParams, handleSessionId, updateSessionIdInUrl, getReferrer, addReferrer, addClientTag, addUIConfId};
6 changes: 3 additions & 3 deletions src/common/utils/setup-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ function validateProviderConfig(providerOptions: ProviderOptionsObject): void {
url: KAVA_DEFAULT_IMPRESSION,
mimetype: ''
};
addReferrer(source);
addClientTag(source);
updateSessionIdInUrl(source, Utils.Generator.guid() + ':' + Utils.Generator.guid());
source.url = addReferrer(source.url);
source.url = addClientTag(source.url);
source.url = updateSessionIdInUrl(source.url, Utils.Generator.guid() + ':' + Utils.Generator.guid());
navigator.sendBeacon && navigator.sendBeacon(source.url);
}
}
Expand Down
80 changes: 72 additions & 8 deletions test/src/common/utils/kaltura-params.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
addKalturaParams,
addReferrer,
getReferrer,
addUIConfId,
handleSessionId,
updateSessionIdInUrl
} from '../../../../src/common/utils/kaltura-params';
Expand Down Expand Up @@ -76,6 +77,46 @@ describe('addKalturaParams', function() {
player.config.session.id.should.be.exist;
source1.url.should.be.equal('a/b/c/PLAYMANIFEST/source');
});

it('should add session id, referrer and client tag for PLAYMANIFEST source and session id, referrer, client tag and uiconfid to udrm license', function() {
let source1 = {url: 'a/b/c/PLAYMANIFEST/source', drmData: [{licenseUrl: 'udrm.kaltura.com?custom_data=someData&signature=Sig'}]};
player.config = {provider: {uiConfId: 123}, sources: {progressive: [source1]}};
addKalturaParams(player, player.config);
source1.url.should.be.equal(
'a/b/c/PLAYMANIFEST/source?playSessionId=' +
player.config.session.id +
'&referrer=' +
btoa(getReferrer().substr(0, 1000)) +
'&clientTag=html5:v' +
__VERSION__
);

source1.drmData[0].licenseUrl.should.be.equal(
'udrm.kaltura.com?custom_data=someData&signature=Sig&sessionId=' +
player.config.session.id +
'&clientTag=html5:v' +
__VERSION__ +
'&referrer=' +
btoa(getReferrer().substr(0, 1000)) +
'&uiConfId=123'
);
});

it('should not add session id, referrer, client tag and uiconfid to other drm system', function() {
let source1 = {url: 'a/b/c/PLAYMANIFEST/source', drmData: [{licenseUrl: 'udrm.other.com?custom_data=someData&signature=Sig'}]};
player.config = {provider: {uiConfId: 123}, sources: {progressive: [source1]}};
addKalturaParams(player, player.config);

source1.drmData[0].licenseUrl.should.be.equal('udrm.other.com?custom_data=someData&signature=Sig');
});

it('should not add session id, referrer, client tag and uiconfid to other drm system', function() {
let source1 = {url: 'a/b/c/PLAYMANIFEST/source', drmData: [{licenseUrl: 'udrm.kaltura.com?custommm_data=someData&signature=Sig'}]};
player.config = {provider: {uiConfId: 123}, sources: {progressive: [source1]}};
addKalturaParams(player, player.config);

source1.drmData[0].licenseUrl.should.be.equal('udrm.kaltura.com?custommm_data=someData&signature=Sig');
});
});

describe('handleSessionId', function() {
Expand All @@ -99,60 +140,83 @@ describe('updateSessionIdInUrl', function() {
it('should add session id to URL as first param', function() {
let source = {url: 'a/b/c/playmanifest/source'};
player.config = {session: {id: '5cc03aa6-c58f-3220-b548-2a698aa54830:33e6d80e-63b3-108a-091d-ccc15998f85b'}};
updateSessionIdInUrl(source, player.config.session.id);
source.url = updateSessionIdInUrl(source.url, player.config.session.id);
source.url.should.be.equal('a/b/c/playmanifest/source?playSessionId=' + player.config.session.id);
});

it('should add session id to URL as second param', function() {
let source = {url: 'a/b/c/playmanifest/source?a'};
player.config = {session: {id: '5cc03aa6-c58f-3220-b548-2a698aa54830:33e6d80e-63b3-108a-091d-ccc15998f85b'}};
updateSessionIdInUrl(source, player.config.session.id);
source.url = updateSessionIdInUrl(source.url, player.config.session.id);
source.url.should.be.equal('a/b/c/playmanifest/source?a&playSessionId=' + player.config.session.id);
});

it('should update session id in URL as first param', function() {
let source = {url: 'a/b/c/playmanifest/source?playSessionId=5cc03aa6-c58f-3220-b548-2a698aa54830:33e6d80e-63b3-108a-091d-ccc15998f85b'};
player.config = {session: {id: '5cc03aa6-c58f-3220-b548-2a698aa54830:33e6d80e-63b3-108a-091d-ccc15998f85b'}};
updateSessionIdInUrl(source, player.config.session.id);
source.url = updateSessionIdInUrl(source.url, player.config.session.id);
source.url.should.be.equal('a/b/c/playmanifest/source?playSessionId=' + player.config.session.id);
});

it('should update session id in URL as second param', function() {
let source = {url: 'a/b/c/playmanifest/source?a&playSessionId=5cc03aa6-c58f-3220-b548-2a698aa54830:b5391ed8-be5d-3a71-e157-f23a1b434121'};
player.config = {session: {id: '5cc03aa6-c58f-3220-b548-2a698aa54830:33e6d80e-63b3-108a-091d-ccc15998f85b'}};
updateSessionIdInUrl(source, player.config.session.id);
source.url = updateSessionIdInUrl(source.url, player.config.session.id);
source.url.should.be.equal('a/b/c/playmanifest/source?a&playSessionId=' + player.config.session.id);
});

it('should update session id in URL with param different than playSessionId', function() {
let source = {url: 'a/b/c/playmanifest/source?testId=5cc03aa6-c58f-3220-b548-2a698aa54830:33e6d80e-63b3-108a-091d-ccc15998f85b'};
player.config = {session: {id: '5cc03aa6-c58f-3220-b548-2a698aa54830:33e6d80e-63b3-108a-091d-ccc15998f85b'}};
source.url = updateSessionIdInUrl(source.url, player.config.session.id, 'testId=');
source.url.should.be.equal('a/b/c/playmanifest/source?testId=' + player.config.session.id);
});
});

describe('addReferrer', function() {
it('should add referrer as first param', function() {
let source = {url: 'a/b/c/playmanifest/source'};
player.config = {session: {}};
addReferrer(source, player);
source.url = addReferrer(source.url);
source.url.should.be.equal('a/b/c/playmanifest/source?referrer=' + btoa(getReferrer().substr(0, 1000)));
});

it('should add referrer as second param', function() {
let source = {url: 'a/b/c/playmanifest/source?a'};
player.config = {session: {}};
addReferrer(source, player);
source.url = addReferrer(source.url);
source.url.should.be.equal('a/b/c/playmanifest/source?a&referrer=' + btoa(getReferrer().substr(0, 1000)));
});
});

describe('addUIConfId', function() {
it('should add uiConfId as first param', function() {
let source = {url: 'a/b/c/playmanifest/source'};
player.config = {provider: {uiConfId: 123}};
source.url = addUIConfId(source.url, player.config);
source.url.should.be.equal('a/b/c/playmanifest/source?uiConfId=123');
});

it('should add uiConfId as second param', function() {
let source = {url: 'a/b/c/playmanifest/source?a'};
player.config = {provider: {uiConfId: 123}};
source.url = addUIConfId(source.url, player.config);
source.url.should.be.equal('a/b/c/playmanifest/source?a&uiConfId=123');
});
});

describe('addClientTag', function() {
it('should add client tag as first param', function() {
let source = {url: 'a/b/c/playmanifest/source'};
player.config = {session: {}};
addClientTag(source, player);
source.url = addClientTag(source.url, player);
source.url.should.be.equal('a/b/c/playmanifest/source?clientTag=html5:v' + __VERSION__);
});

it('should add client tag as second param', function() {
let source = {url: 'a/b/c/playmanifest/source?a'};
player.config = {session: {}};
addClientTag(source, player);
source.url = addClientTag(source.url, player);
source.url.should.be.equal('a/b/c/playmanifest/source?a&clientTag=html5:v' + __VERSION__);
});
});

0 comments on commit c7f7748

Please sign in to comment.