UNPKG

@splitsoftware/splitio-commons

Version:
84 lines (83 loc) 3.96 kB
import { decorateHeaders } from '../../../services/decorateHeaders'; import { isString } from '../../../utils/lang'; import { objectAssign } from '../../../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: 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 objectAssign(isServerSide ? { headers: decorateHeaders(this.settings, this.headers) } : ((_a = this.settings.sync.requestOptions) === null || _a === void 0 ? void 0 : _a.getHeaderOverrides) ? { headers: 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; }()); export { SSEClient };