mattermost-redux
Version:
Common code (API client, Redux stores, logic, utility functions) for building a Mattermost client
205 lines • 8.73 kB
JavaScript
;
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var MAX_WEBSOCKET_FAILS = 7;
var MIN_WEBSOCKET_RETRY_TIME = 3000; // 3 sec
var MAX_WEBSOCKET_RETRY_TIME = 300000; // 5 mins
var Socket;
var WebSocketClient = /** @class */ (function () {
function WebSocketClient() {
this.connectionUrl = null;
this.token = null;
this.sequence = 1;
this.connectFailCount = 0;
this.stop = false;
this.platform = '';
}
WebSocketClient.prototype.initialize = function (token, opts) {
var _this = this;
var defaults = {
forceConnection: true,
connectionUrl: this.connectionUrl,
webSocketConnector: WebSocket,
};
var _a = Object.assign({}, defaults, opts), connectionUrl = _a.connectionUrl, forceConnection = _a.forceConnection, webSocketConnector = _a.webSocketConnector, platform = _a.platform, additionalOptions = tslib_1.__rest(_a, ["connectionUrl", "forceConnection", "webSocketConnector", "platform"]);
if (platform) {
this.platform = platform;
}
if (forceConnection) {
this.stop = false;
}
return new Promise(function (resolve, reject) {
if (_this.conn) {
resolve();
return;
}
if (connectionUrl == null) {
console.log('websocket must have connection url'); //eslint-disable-line no-console
reject(new Error('websocket must have connection url'));
return;
}
if (_this.connectFailCount === 0) {
console.log('websocket connecting to ' + connectionUrl); //eslint-disable-line no-console
}
Socket = webSocketConnector;
if (_this.connectingCallback) {
_this.connectingCallback();
}
var regex = /^(?:https?|wss?):(?:\/\/)?[^/]*/;
var captured = (regex).exec(connectionUrl);
var origin;
if (captured) {
origin = captured[0];
if (platform === 'android') {
// this is done cause for android having the port 80 or 443 will fail the connection
// the websocket will append them
var split = origin.split(':');
var port = split[2];
if (port === '80' || port === '443') {
origin = split[0] + ":" + split[1];
}
}
}
else {
// If we're unable to set the origin header, the websocket won't connect, but the URL is likely malformed anyway
var errorMessage = 'websocket failed to parse origin from ' + connectionUrl;
console.warn(errorMessage); // eslint-disable-line no-console
reject(new Error(errorMessage));
return;
}
_this.conn = new Socket(connectionUrl, [], tslib_1.__assign({ headers: { origin: origin } }, (additionalOptions || {})));
_this.connectionUrl = connectionUrl;
_this.token = token;
_this.conn.onopen = function () {
if (token) {
// we check for the platform as a workaround until we fix on the server that further authentications
// are ignored
_this.sendMessage('authentication_challenge', { token: token });
}
if (_this.connectFailCount > 0) {
console.log('websocket re-established connection'); //eslint-disable-line no-console
if (_this.reconnectCallback) {
_this.reconnectCallback();
}
}
else if (_this.firstConnectCallback) {
_this.firstConnectCallback();
}
_this.connectFailCount = 0;
resolve();
};
_this.conn.onclose = function () {
_this.conn = undefined;
_this.sequence = 1;
if (_this.connectFailCount === 0) {
console.log('websocket closed'); //eslint-disable-line no-console
}
_this.connectFailCount++;
if (_this.closeCallback) {
_this.closeCallback(_this.connectFailCount);
}
var retryTime = MIN_WEBSOCKET_RETRY_TIME;
// If we've failed a bunch of connections then start backing off
if (_this.connectFailCount > MAX_WEBSOCKET_FAILS) {
retryTime = MIN_WEBSOCKET_RETRY_TIME * _this.connectFailCount;
if (retryTime > MAX_WEBSOCKET_RETRY_TIME) {
retryTime = MAX_WEBSOCKET_RETRY_TIME;
}
}
if (_this.connectionTimeout) {
clearTimeout(_this.connectionTimeout);
}
_this.connectionTimeout = setTimeout(function () {
if (_this.stop) {
clearTimeout(_this.connectionTimeout);
return;
}
_this.initialize(token, opts);
}, retryTime);
};
_this.conn.onerror = function (evt) {
if (_this.connectFailCount <= 1) {
console.log('websocket error'); //eslint-disable-line no-console
console.log(evt); //eslint-disable-line no-console
}
if (_this.errorCallback) {
_this.errorCallback(evt);
}
};
_this.conn.onmessage = function (evt) {
var msg = JSON.parse(evt.data);
if (msg.seq_reply) {
if (msg.error) {
console.warn(msg); //eslint-disable-line no-console
}
}
else if (_this.eventCallback) {
_this.eventCallback(msg);
}
};
});
};
WebSocketClient.prototype.setConnectingCallback = function (callback) {
this.connectingCallback = callback;
};
WebSocketClient.prototype.setEventCallback = function (callback) {
this.eventCallback = callback;
};
WebSocketClient.prototype.setFirstConnectCallback = function (callback) {
this.firstConnectCallback = callback;
};
WebSocketClient.prototype.setReconnectCallback = function (callback) {
this.reconnectCallback = callback;
};
WebSocketClient.prototype.setErrorCallback = function (callback) {
this.errorCallback = callback;
};
WebSocketClient.prototype.setCloseCallback = function (callback) {
this.closeCallback = callback;
};
WebSocketClient.prototype.close = function (stop) {
if (stop === void 0) { stop = false; }
this.stop = stop;
this.connectFailCount = 0;
this.sequence = 1;
if (this.conn && this.conn.readyState === Socket.OPEN) {
this.conn.onclose = function () { }; //eslint-disable-line @typescript-eslint/no-empty-function
this.conn.close();
this.conn = undefined;
console.log('websocket closed'); //eslint-disable-line no-console
}
};
WebSocketClient.prototype.sendMessage = function (action, data) {
var msg = {
action: action,
seq: this.sequence++,
data: data,
};
if (this.conn && this.conn.readyState === Socket.OPEN) {
this.conn.send(JSON.stringify(msg));
}
else if (!this.conn || this.conn.readyState === Socket.CLOSED) {
this.conn = undefined;
this.initialize(this.token, { platform: this.platform });
}
};
WebSocketClient.prototype.userTyping = function (channelId, parentId) {
this.sendMessage('user_typing', {
channel_id: channelId,
parent_id: parentId,
});
};
WebSocketClient.prototype.getStatuses = function () {
this.sendMessage('get_statuses', null);
};
WebSocketClient.prototype.getStatusesByIds = function (userIds) {
this.sendMessage('get_statuses_by_ids', {
user_ids: userIds,
});
};
return WebSocketClient;
}());
exports.default = new WebSocketClient();
//# sourceMappingURL=websocket_client.js.map