kui-shell
Version:
This is the monorepo for Kui, the hybrid command-line/GUI electron-based Kubernetes tool
224 lines • 11.8 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const debug_1 = require("debug");
const uuid_1 = require("uuid");
const core_1 = require("@kui-shell/core");
const mimic_dom_1 = require("@kui-shell/core/util/mimic-dom");
const config_1 = require("./config");
function getSessionForTab(tab) {
return tab['_kui_session'];
}
const debug = debug_1.default('plugins/proxy-support/executor');
const defaultProxyServerConfig_1 = require("./defaultProxyServerConfig");
const proxyServerConfig = core_1.Settings.config['proxyServer'] || defaultProxyServerConfig_1.default;
debug('proxyServerConfig', proxyServerConfig);
const directEvaluator = new core_1.REPL.DirectReplEval();
function renderDom(content) {
const dom = document.createElement(content.nodeType || 'span');
if (content.className.length > 0) {
dom.className = content.className;
}
else if (content.classList.classList.length > 0) {
content.classList.classList.forEach(_ => {
dom.classList.add(_);
});
}
if (content.innerText) {
dom.innerText = content.innerText;
}
else if (content.children && content.children.length > 0) {
content.children.forEach(child => {
dom.appendChild(renderDom(child));
});
}
return dom;
}
class ProxyEvaluator {
constructor() {
this.name = 'ProxyEvaluator';
}
apply(command, execOptions, evaluator, args) {
return __awaiter(this, void 0, void 0, function* () {
debug('apply', evaluator);
debug('execOptions', execOptions);
if (config_1.isDisabled(proxyServerConfig) ||
(core_1.Commands.isCommandHandlerWithEvents(evaluator) &&
evaluator.options &&
!execOptions.forceProxy &&
(evaluator.options.inBrowserOk || evaluator.options.needsUI))) {
debug('delegating to direct evaluator');
return directEvaluator.apply(command, execOptions, evaluator, args);
}
else {
const execOptionsForInvoke = core_1.Commands.withLanguage(Object.assign({}, execOptions, {
isProxied: true,
cwd: process.env.PWD,
env: process.env,
credentials: core_1.Capabilities.getValidCredentials(),
tab: undefined,
rawResponse: true
}));
if (command !== 'bash websocket open') {
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
const uuid = uuid_1.v4();
debug('delegating to proxy websocket', command, uuid);
const channel = yield getSessionForTab(args.tab);
const msg = {
type: 'request',
cmdline: command,
uuid,
cwd: process.env.PWD,
execOptions: execOptionsForInvoke
};
channel.send(JSON.stringify(msg));
const MARKER = '\n';
let raw = '';
const onMessage = (data) => {
raw += data;
if (data.endsWith(MARKER)) {
raw += data;
try {
raw
.split(MARKER)
.filter(_ => _)
.forEach(_ => {
const response = JSON.parse(_);
if (response.uuid === uuid) {
channel.removeEventListener('message', onMessage);
const code = response.response.code || response.response.statusCode;
if (code !== undefined && code !== 200) {
if (core_1.Errors.isUsageError(response.response)) {
debug('rejecting as usage error', response);
reject(response.response);
}
else {
debug('rejecting as other error', response);
const err = new Error(response.response.message);
err.stack = response.response.stack;
err.code = err.statusCode = code;
err.body = response.response;
reject(err);
}
}
else if (mimic_dom_1.ElementMimic.isFakeDom(response.response)) {
debug('rendering fakedom', response.response);
resolve(renderDom(response.response));
}
else if (mimic_dom_1.ElementMimic.isFakeDom(response.response.content)) {
debug('rendering fakedom content', response.response.content);
response.response.content = renderDom(response.response.content);
resolve(response.response);
}
else {
debug('response', response);
resolve(response.response);
}
}
});
}
catch (err) {
console.error('error handling response', raw);
console.error(err);
reject(new Error('Internal Error'));
}
}
};
channel.on('message', onMessage);
}));
}
debug('delegating to proxy exec', command);
const body = {
command,
execOptions: execOptionsForInvoke
};
debug('sending body', body);
try {
const invokeRemote = () => new Promise(resolve => {
const proxyURL = new URL(proxyServerConfig.url, window.location.origin);
const xhr = new XMLHttpRequest();
xhr.open('POST', proxyURL.href);
xhr.responseType = 'json';
xhr.withCredentials = true;
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Accept', 'application/json');
xhr.addEventListener('error', () => {
if (xhr.readyState === 4 && xhr.status === 0) {
resolve({
statusCode: 503,
code: 503,
body: 'Connection refused'
});
}
else {
console.error('error in xhr', xhr.status, xhr);
resolve(xhr.response || 'Internal Error');
}
});
xhr.addEventListener('load', () => {
resolve({
statusCode: xhr.status,
body: xhr.response.response
});
});
xhr.send(JSON.stringify(body));
});
const response = yield (window['webview-proxy']
? window['webview-proxy'](body)
: invokeRemote());
debug('response', response);
if (response.statusCode !== 200) {
debug('rethrowing non-200 response', response);
const err = new Error(response.body);
err.code = err.statusCode = response.statusCode;
err.body = response.body;
throw err;
}
else {
if (mimic_dom_1.ElementMimic.isFakeDom(response.body)) {
debug('catch a fakedom, try to unwind');
if (response.body.innerText) {
return response.body.innerText;
}
else {
const err = new Error('Internal Error: Fakedom objects are not accepted by proxy executor');
err['code'] = 500;
throw err;
}
}
return response.body;
}
}
catch (err) {
debug('proxy execution resulted in an error, recasting to local exception', err.code, err.message, err.body, err);
if (err.body && core_1.Errors.isUsageError(err.body)) {
debug('the error is a usage error, rethrowing as such');
throw new core_1.Errors.UsageError({
message: err.body.raw.message,
usage: err.body.raw.usage,
code: err.body.code,
extra: err.body.extra
});
}
else {
const error = new Error((err.body && err.body.message) ||
(typeof err.body === 'string' ? err.body : err.message || 'Internal error'));
error.code = error.statusCode = (err.body && err.body.code) || err.code || err.statusCode;
debug('using this code', error.code);
throw error;
}
}
}
});
}
}
exports.default = ProxyEvaluator;
//# sourceMappingURL=proxy-executor.js.map