mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
* [plugins] extract plugin discover from the kibana server
* integrate plugin discovery module with server
* [pluginDiscovery] fully extend config before checking enabled status
* [pluginDiscovery] limit arbitrary defaults in PluginSpec
* [ui/navLink] fix tests
* [ui/injectedVars] fix tests
* [ui/app] fix tests
* [server/plugins] convert init to callPluginHook tests
* [build/verifyTranslations] update verify logic
* [pluginDiscovery] remove rx utils
* fix i18n transaltion key name
* [pluginDiscovery] do kibana version checks as a part of discovery
* [pluginDiscovery/createPacksInDirectory$] clarify error handling
* [eslint] fix lint errors
* [uiApp/modules] ensure load order matches master
* [uiBundle] use known uiExport type for providers
* [uiExports] use the `home` export type
* [uiExports] validate that all uiExport types are known
* [timelion] remove archaic/broken bwc check
* revert some stragler changes
* [pluginSpecs] reformat comments
* [uiBundle] rebel and use more fcb 😬
* correct comment
* [server/waitForPluginsInit] describe queues var
* [server/plugins] prevent multiple calls to next() by using single then()
* [uiApp] remove archaic deprecation warning
* [uiApp] tighten up tests
* [pluginDiscovery/errors] remove $ from symbol var
* [pluginDiscovery/reduceExportSpecs] update docs
* [pluginDiscovery/findPluginSpecs] rightVersion -> isRightVersion
* [pluginDiscovery/findPluginSpecs] fix typos
* [uiApps/getById] use Map() rather than memoize
* save
* [savedObjects/mappings] use uiExports.savedObjectMappings
* [server/mapping/indexMapping] update tests, addRootProperties method removed
* [uiExports] "embeddableHandlers" -> "embeddableFactories"
* [pluginDiscovery] fix pluralization of invalidVersionSpec$
* [pluginDiscover] add README
* [pluginDiscovery/reduceExportSpecs] don't ignore fasly spec values, just undefined
* [ui/exportTypes] use better reducer names
* [ui/uiExports] add README
* fix links
* [pluginDiscovery/readme] expand examples
* [pluginDiscovery/readme] clean up reduceExportSpecs() doc
* [ui/uiExports/readme] cleanup example
* [pluginDiscovery] remove needless use of lodash
* [pluginDiscovery/waitForComplete] use better name
* [pluginDiscovery/findPluginSpecs] use fixtures rather than core_plugins
* [pluginDiscovery/stubSchema] use deafult: false
* [plguinDiscovery/pluginConfig] add tests
* typo
* [uiExports/readme] fix link
* [pluginDiscovery/packAtPath] fail with InvalidPackError if path is not a string
* [pluginDiscovery/packAtPath] rely on error.code to detect missing package.json file
* [pluginDiscovery/packAtPath] only attempt to get pack when observable is subscribed
* [pluginDiscovery/packAtPath] add tests
* [pluginDiscovery/pluginPack] move absolute path checks into fs lib
* [pluginDiscovery/packsInDirectory] fix error type check
* [pluginDiscovery/pluginPack/tests] share some utils
* [pluginDiscovery/packsInDirectory] add tests
* [pluginDiscovery/pluginPack] only cast undefined to array
* [pluginDiscovery/pluginPack] add tests
* [pluginDiscovery/pluginSpec/isVersionCompatible] add tests
* [pluginDiscovery/InvalidPluginError] be less redundant
* [pluginDiscovery/pluginSpec] verify config service is passed to isEnabled()
* [pluginDiscovery/pluginSpec] add tests
* fix "existent" spelling
133 lines
4 KiB
JavaScript
133 lines
4 KiB
JavaScript
import { Server } from 'hapi';
|
|
import { notFound } from 'boom';
|
|
import { map, sample } from 'lodash';
|
|
import { format as formatUrl } from 'url';
|
|
import { map as promiseMap, fromNode } from 'bluebird';
|
|
import { Agent as HttpsAgent } from 'https';
|
|
import { readFileSync } from 'fs';
|
|
|
|
import { Config } from '../../server/config/config';
|
|
import setupConnection from '../../server/http/setup_connection';
|
|
import registerHapiPlugins from '../../server/http/register_hapi_plugins';
|
|
import setupLogging from '../../server/logging';
|
|
import { transformDeprecations } from '../../server/config/transform_deprecations';
|
|
|
|
const alphabet = 'abcdefghijklmnopqrztuvwxyz'.split('');
|
|
|
|
export default class BasePathProxy {
|
|
constructor(clusterManager, userSettings) {
|
|
this.clusterManager = clusterManager;
|
|
this.server = new Server();
|
|
|
|
const settings = transformDeprecations(userSettings);
|
|
const config = Config.withDefaultSchema(settings);
|
|
|
|
this.targetPort = config.get('dev.basePathProxyTarget');
|
|
this.basePath = config.get('server.basePath');
|
|
|
|
const sslEnabled = config.get('server.ssl.enabled');
|
|
if (sslEnabled) {
|
|
this.proxyAgent = new HttpsAgent({
|
|
key: readFileSync(config.get('server.ssl.key')),
|
|
passphrase: config.get('server.ssl.keyPassphrase'),
|
|
cert: readFileSync(config.get('server.ssl.certificate')),
|
|
ca: map(config.get('server.ssl.certificateAuthorities'), readFileSync),
|
|
rejectUnauthorized: false
|
|
});
|
|
}
|
|
|
|
if (!this.basePath) {
|
|
this.basePath = `/${sample(alphabet, 3).join('')}`;
|
|
config.set('server.basePath', this.basePath);
|
|
}
|
|
|
|
const ONE_GIGABYTE = 1024 * 1024 * 1024;
|
|
config.set('server.maxPayloadBytes', ONE_GIGABYTE);
|
|
|
|
setupLogging(null, this.server, config);
|
|
setupConnection(null, this.server, config);
|
|
registerHapiPlugins(null, this.server, config);
|
|
|
|
this.setupRoutes();
|
|
}
|
|
|
|
setupRoutes() {
|
|
const { clusterManager, server, basePath, targetPort } = this;
|
|
|
|
server.route({
|
|
method: 'GET',
|
|
path: '/',
|
|
handler(req, reply) {
|
|
return reply.redirect(basePath);
|
|
}
|
|
});
|
|
|
|
server.route({
|
|
method: '*',
|
|
path: `${basePath}/{kbnPath*}`,
|
|
config: {
|
|
pre: [
|
|
(req, reply) => {
|
|
promiseMap(clusterManager.workers, worker => {
|
|
if (worker.type === 'server' && !worker.listening && !worker.crashed) {
|
|
return fromNode(cb => {
|
|
const done = () => {
|
|
worker.removeListener('listening', done);
|
|
worker.removeListener('crashed', done);
|
|
cb();
|
|
};
|
|
|
|
worker.on('listening', done);
|
|
worker.on('crashed', done);
|
|
});
|
|
}
|
|
})
|
|
.return(undefined)
|
|
.nodeify(reply);
|
|
}
|
|
],
|
|
},
|
|
handler: {
|
|
proxy: {
|
|
passThrough: true,
|
|
xforward: true,
|
|
agent: this.proxyAgent,
|
|
mapUri(req, callback) {
|
|
callback(null, formatUrl({
|
|
protocol: server.info.protocol,
|
|
hostname: server.info.host,
|
|
port: targetPort,
|
|
pathname: req.params.kbnPath,
|
|
query: req.query,
|
|
}));
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
server.route({
|
|
method: '*',
|
|
path: `/{oldBasePath}/{kbnPath*}`,
|
|
handler(req, reply) {
|
|
const { oldBasePath, kbnPath = '' } = req.params;
|
|
|
|
const isGet = req.method === 'get';
|
|
const isBasePath = oldBasePath.length === 3;
|
|
const isApp = kbnPath.startsWith('app/');
|
|
const isKnownShortPath = ['login', 'logout', 'status'].includes(kbnPath);
|
|
|
|
if (isGet && isBasePath && (isApp || isKnownShortPath)) {
|
|
return reply.redirect(`${basePath}/${kbnPath}`);
|
|
}
|
|
|
|
return reply(notFound());
|
|
}
|
|
});
|
|
}
|
|
|
|
async listen() {
|
|
await fromNode(cb => this.server.start(cb));
|
|
this.server.log(['listening', 'info'], `basePath Proxy running at ${this.server.info.uri}${this.basePath}`);
|
|
}
|
|
|
|
}
|