UNPKG

kui-shell

Version:

This is the monorepo for Kui, the hybrid command-line/GUI electron-based Kubernetes tool

224 lines 11.8 kB
"use strict"; 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