@splitsoftware/splitio-commons
Version:
Split JavaScript SDK common components
87 lines (86 loc) • 4.15 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SSEClient = void 0;
var decorateHeaders_1 = require("../../../services/decorateHeaders");
var lang_1 = require("../../../utils/lang");
var objectAssign_1 = require("../../../utils/lang/objectAssign");
var ABLY_API_VERSION = '1.1';
var CONTROL_CHANNEL_REGEX = /^control_/;
/**
* Build metadata headers for SSE connection.
*
* @param settings - Validated settings.
* @returns Headers object
*/
function buildSSEHeaders(settings) {
var headers = {
SplitSDKClientKey: (0, lang_1.isString)(settings.core.authorizationKey) ? settings.core.authorizationKey.slice(-4) : '',
SplitSDKVersion: settings.version,
};
// ip and hostname are false if IPAddressesEnabled is false
var _a = settings.runtime, ip = _a.ip, hostname = _a.hostname;
if (ip)
headers['SplitSDKMachineIP'] = ip;
if (hostname)
headers['SplitSDKMachineName'] = hostname;
return headers;
}
/**
* Handles streaming connections with EventSource API
*/
var SSEClient = /** @class */ (function () {
/**
* SSEClient constructor.
*
* @param settings - Validated settings.
* @param platform - object containing environment-specific dependencies
* @throws 'EventSource API is not available.' if EventSource is not available.
*/
function SSEClient(settings, _a) {
var getEventSource = _a.getEventSource, getOptions = _a.getOptions;
this.settings = settings;
this.eventSource = getEventSource && getEventSource(settings);
// if eventSource is not available, throw an exception
if (!this.eventSource)
throw new Error('EventSource API is not available.');
this.headers = buildSSEHeaders(settings);
this.options = getOptions && getOptions(settings);
}
SSEClient.prototype.setEventHandler = function (handler) {
this.handler = handler;
};
/**
* Open the connection with a given authToken
*/
SSEClient.prototype.open = function (authToken) {
var _a;
this.close(); // it closes connection if previously opened
var channelsQueryParam = Object.keys(authToken.channels).map(function (channel) {
var params = CONTROL_CHANNEL_REGEX.test(channel) ? '[?occupancy=metrics.publishers]' : '';
return encodeURIComponent(params + channel);
}).join(',');
var url = this.settings.urls.streaming + "/sse?channels=" + channelsQueryParam + "&accessToken=" + authToken.token + "&v=" + ABLY_API_VERSION + "&heartbeats=true"; // same results using `&heartbeats=false`
var isServerSide = !this.settings.core.key;
this.connection = new this.eventSource(
// For client-side SDKs, metadata is passed as query param to avoid CORS issues and because native EventSource implementations in browsers do not support headers
isServerSide ? url : url + ("&SplitSDKVersion=" + this.headers.SplitSDKVersion + "&SplitSDKClientKey=" + this.headers.SplitSDKClientKey),
// For server-side SDKs, metadata is passed via headers
(0, objectAssign_1.objectAssign)(isServerSide ?
{ headers: (0, decorateHeaders_1.decorateHeaders)(this.settings, this.headers) } :
((_a = this.settings.sync.requestOptions) === null || _a === void 0 ? void 0 : _a.getHeaderOverrides) ?
{ headers: (0, decorateHeaders_1.decorateHeaders)(this.settings, {}) } : // User must provide a window.EventSource polyfill that supports headers
{}, this.options));
if (this.handler) { // no need to check if SSEClient is used only by PushManager
this.connection.addEventListener('open', this.handler.handleOpen);
this.connection.addEventListener('message', this.handler.handleMessage);
this.connection.addEventListener('error', this.handler.handleError);
}
};
/** Close connection */
SSEClient.prototype.close = function () {
if (this.connection)
this.connection.close();
};
return SSEClient;
}());
exports.SSEClient = SSEClient;