UNPKG

@splitsoftware/splitio-commons

Version:
87 lines (86 loc) 4.15 kB
"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;