UNPKG

@hpcc-js/comms

Version:
200 lines 7.84 kB
import * as tslib_1 from "tslib"; import { join, promiseTimeout, scopedLogger } from "@hpcc-js/util"; var logger = scopedLogger("comms/connection.ts"); var DefaultOptions = { type: "post", baseUrl: "", userID: "", password: "", rejectUnauthorized: false, timeoutSecs: 60 }; // comms --- export function serializeRequest(obj, prefix) { if (prefix === void 0) { prefix = ""; } if (prefix) { prefix += "."; } if (typeof obj !== "object") { return encodeURIComponent(obj); } var str = []; var _loop_1 = function (key) { if (obj.hasOwnProperty(key)) { if (obj[key] instanceof Array) { // Specific to ESP - but no REST standard exists... var includeItemCount_1 = false; obj[key].forEach(function (row, i) { if (typeof row === "object") { includeItemCount_1 = true; str.push(serializeRequest(row, prefix + encodeURIComponent(key + "." + i))); } else { str.push(prefix + encodeURIComponent(key + "_i" + i) + "=" + serializeRequest(row)); } }); if (includeItemCount_1) { str.push(prefix + encodeURIComponent(key + ".itemcount") + "=" + obj[key].length); } } else if (typeof obj[key] === "object") { if (obj[key] && obj[key]["Item"] instanceof Array) { // Specific to ws_machine.GetTargetClusterInfo? str.push(serializeRequest(obj[key]["Item"], prefix + encodeURIComponent(key))); str.push(prefix + encodeURIComponent(key + ".itemcount") + "=" + obj[key]["Item"].length); } else { str.push(serializeRequest(obj[key], prefix + encodeURIComponent(key))); } } else if (obj[key] !== undefined) { str.push(prefix + encodeURIComponent(key) + "=" + encodeURIComponent(obj[key])); } else { str.push(prefix + encodeURIComponent(key)); } } }; for (var key in obj) { _loop_1(key); } return str.join("&"); } export function deserializeResponse(body) { return JSON.parse(body); } export function jsonp(opts, action, request, responseType) { if (request === void 0) { request = {}; } if (responseType === void 0) { responseType = "json"; } return new Promise(function (resolve, reject) { var respondedTimeout = opts.timeoutSecs * 1000; var respondedTick = 5000; var callbackName = "jsonp_callback_" + Math.round(Math.random() * 999999); window[callbackName] = function (response) { respondedTimeout = 0; doCallback(); resolve(responseType === "json" && typeof response === "string" ? deserializeResponse(response) : response); }; var script = document.createElement("script"); var url = join(opts.baseUrl, action); url += url.indexOf("?") >= 0 ? "&" : "?"; script.src = url + "jsonp=" + callbackName + "&" + serializeRequest(request); document.body.appendChild(script); var progress = setInterval(function () { if (respondedTimeout <= 0) { clearInterval(progress); } else { respondedTimeout -= respondedTick; if (respondedTimeout <= 0) { clearInterval(progress); logger.error("Request timeout: " + script.src); doCallback(); reject(Error("Request timeout: " + script.src)); } else { logger.debug("Request pending (" + respondedTimeout / 1000 + " sec): " + script.src); } } }, respondedTick); function doCallback() { delete window[callbackName]; document.body.removeChild(script); } }); } function authHeader(opts) { return opts.userID ? { Authorization: "Basic " + btoa(opts.userID + ":" + opts.password) } : {}; } // _omitMap is a workaround for older HPCC-Platform instances without credentials --- var _omitMap = {}; function doFetch(opts, action, requestInit, headersInit, responseType) { headersInit = tslib_1.__assign({}, authHeader(opts), headersInit); requestInit = tslib_1.__assign({ credentials: _omitMap[opts.baseUrl] ? "omit" : "include" }, requestInit, { headers: headersInit }); function handleResponse(response) { if (response.ok) { return responseType === "json" ? response.json() : response.text(); } throw new Error(response.statusText); } return promiseTimeout(opts.timeoutSecs * 1000, fetch(join(opts.baseUrl, action), requestInit) .then(handleResponse) .catch(function (e) { // Try again with the opposite credentials mode --- requestInit.credentials = !_omitMap[opts.baseUrl] ? "omit" : "include"; return fetch(join(opts.baseUrl, action), requestInit) .then(handleResponse) .then(function (responseBody) { _omitMap[opts.baseUrl] = !_omitMap[opts.baseUrl]; // The "opposite" credentials mode is known to work --- return responseBody; }); })); } export function post(opts, action, request, responseType) { if (responseType === void 0) { responseType = "json"; } return doFetch(opts, action, { method: "post", body: serializeRequest(request) }, { "Content-Type": "application/x-www-form-urlencoded" }, responseType); } export function get(opts, action, request, responseType) { if (responseType === void 0) { responseType = "json"; } return doFetch(opts, action + "?" + serializeRequest(request), { method: "get" }, {}, responseType); } export function send(opts, action, request, responseType) { if (responseType === void 0) { responseType = "json"; } var retVal; switch (opts.type) { case "jsonp": retVal = jsonp(opts, action, request, responseType); break; case "get": retVal = get(opts, action, request, responseType); break; case "post": default: retVal = post(opts, action, request, responseType); break; } return retVal; } var hookedSend = send; export function hookSend(newSend) { var retVal = hookedSend; if (newSend) { hookedSend = newSend; } return retVal; } var Connection = /** @class */ (function () { function Connection(opts) { this.opts(opts); } Connection.prototype.opts = function (_) { if (arguments.length === 0) return this._opts; this._opts = tslib_1.__assign({}, DefaultOptions, _); return this; }; Connection.prototype.send = function (action, request, responseType) { if (responseType === void 0) { responseType = "json"; } return hookedSend(this._opts, action, request, responseType); }; Connection.prototype.clone = function () { return new Connection(this.opts()); }; return Connection; }()); export { Connection }; export var createConnection = function (opts) { return new Connection(opts); }; export function setTransportFactory(newFunc) { var retVal = createConnection; createConnection = newFunc; return retVal; } //# sourceMappingURL=connection.js.map