UNPKG

@webex/webex-core

Version:

Plugin handling for Cisco Webex

202 lines (187 loc) • 7.76 kB
"use strict"; var _Reflect$construct = require("@babel/runtime-corejs2/core-js/reflect/construct"); var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property"); var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault"); _Object$defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass")); var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/assertThisInitialized")); var _inherits2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/inherits")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/getPrototypeOf")); var _weakMap = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/weak-map")); var _map = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/map")); var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise")); var _httpCore = require("@webex/http-core"); function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = _Reflect$construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !_Reflect$construct) return false; if (_Reflect$construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } /*! * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file. */ // contains the system time in milliseconds at which the retry after associated with a 429 expires // mapped by the API name, e.g.: idbroker.webex.com/doStuff would be mapped as 'doStuff' var rateLimitExpiryTime = new _weakMap.default(); // extracts the common identity API being called var idBrokerRegex = /.*(idbroker|identity)(bts)?.ciscospark.com\/([^/]+)/; /** * @class */ var RateLimitInterceptor = exports.default = /*#__PURE__*/function (_Interceptor) { (0, _inherits2.default)(RateLimitInterceptor, _Interceptor); var _super = _createSuper(RateLimitInterceptor); /** * constructor * @param {mixed} args * @returns {Exception} */ function RateLimitInterceptor() { var _this; (0, _classCallCheck2.default)(this, RateLimitInterceptor); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _super.call.apply(_super, [this].concat(args)); rateLimitExpiryTime.set((0, _assertThisInitialized2.default)(_this), new _map.default()); return _this; } /** * @see {@link Interceptor#onRequest} * @param {Object} options * @returns {Object} */ (0, _createClass2.default)(RateLimitInterceptor, [{ key: "onRequest", value: function onRequest(options) { if (this.isRateLimited(options.uri)) { return _promise.default.reject(new Error("API rate limited ".concat(options.uri))); } return _promise.default.resolve(options); } /** * @see {@link Interceptor#onResponseError} * @param {Object} options * @param {Error} reason * @returns {Object} */ }, { key: "onResponseError", value: function onResponseError(options, reason) { if (reason.statusCode === 429 && (options.uri.includes('idbroker') || options.uri.includes('identity'))) { // set the retry after in the map, setting to milliseconds this.setRateLimitExpiry(options.uri, this.extractRetryAfterTime(options)); } return _promise.default.reject(reason); } /** * @param {object} options associated with the request * @returns {number} retry after time in milliseconds */ }, { key: "extractRetryAfterTime", value: function extractRetryAfterTime(options) { // 1S * 1K === 1MS var milliMultiplier = 1000; var retryAfter = options.headers['retry-after'] || null; // set 60 retry if no usable time defined if (retryAfter === null || retryAfter <= 0) { return 60 * milliMultiplier; } // set max to 3600 S (1 hour) if greater than 1 hour if (retryAfter > 3600) { return 3600 * milliMultiplier; } return retryAfter * milliMultiplier; } /** * Set the system time at which the rate limiting * will expire in the rateLimitExpiryTime map. * Assumes retryAfter is in milliseconds * @param {string} uri API issuing the rate limiting * @param {number} retryAfter milliseconds until rate limiting expires * @returns {bool} true is value was successfully set */ }, { key: "setRateLimitExpiry", value: function setRateLimitExpiry(uri, retryAfter) { var apiName = this.getApiName(uri); if (!apiName) { return false; } var currTimeMilli = new Date().getTime(); var expiry = currTimeMilli + retryAfter; var dict = rateLimitExpiryTime.get(this); return dict.set(apiName, expiry); } /** * returns true if the API is currently rate limited * @param {string} uri * @returns {Boolean} indicates whether or not the API is rate currently rate limited */ }, { key: "getRateLimitStatus", value: function getRateLimitStatus(uri) { var apiName = this.getApiName(uri); if (!apiName) { return false; } var currTimeMilli = new Date().getTime(); var dict = rateLimitExpiryTime.get(this); var expiryTime = dict.get(apiName); // if no rate limit expiry has been registered in the map, return false. if (expiryTime === undefined) { return false; } // return true, indicating rate limiting, if the system time is less than the expiry time return currTimeMilli < dict.get(apiName); } /** * split the URI and returns the API name of idBroker * @param {string} uri * @returns {string} */ }, { key: "getApiName", value: function getApiName(uri) { if (!uri) { return null; } var results = uri.match(idBrokerRegex); if (!results) { return null; } // group 0 = full match of URL, group 1 = identity or idbroker base // group 2 = api name return results[2]; } /** * check URI against list of currently rate limited * URIs, and determines if retry-after * @param {String} uri pattern to check * @returns {bool} */ }, { key: "isRateLimited", value: function isRateLimited(uri) { // determine if the URI is associated with a common identity API if (uri && (uri.includes('idbroker') || uri.includes('identity'))) { return this.getRateLimitStatus(uri); } return false; } }], [{ key: "create", value: /** * @returns {RateLimitInterceptor} */ function create() { return new RateLimitInterceptor({ webex: this }); } }]); return RateLimitInterceptor; }(_httpCore.Interceptor); //# sourceMappingURL=rate-limit.js.map