UNPKG

@backstage/backend-defaults

Version:

Backend defaults used by Backstage backend apps

157 lines (153 loc) 5.39 kB
'use strict'; var config = require('../rootHttpRouter/http/config.cjs.js'); var SrvResolvers = require('./SrvResolvers.cjs.js'); var lodash = require('lodash'); class HostDiscovery { #srvResolver; #internalResolvers = /* @__PURE__ */ new Map(); #externalResolvers = /* @__PURE__ */ new Map(); #internalFallbackResolver = async () => { throw new Error("Not initialized"); }; #externalFallbackResolver = async () => { throw new Error("Not initialized"); }; static fromConfig(config, options) { const discovery = new HostDiscovery(new SrvResolvers.SrvResolvers()); discovery.#updateResolvers(config, options?.defaultEndpoints); config.subscribe?.(() => { try { discovery.#updateResolvers(config, options?.defaultEndpoints); } catch (e) { options?.logger.error(`Failed to update discovery service: ${e}`); } }); return discovery; } constructor(srvResolver) { this.#srvResolver = srvResolver; this.#internalResolvers = /* @__PURE__ */ new Map(); this.#externalResolvers = /* @__PURE__ */ new Map(); this.#internalFallbackResolver = () => { throw new Error("Not initialized"); }; this.#externalFallbackResolver = () => { throw new Error("Not initialized"); }; } async getBaseUrl(pluginId) { const resolver = this.#internalResolvers.get(pluginId) ?? this.#internalResolvers.get("*") ?? this.#internalFallbackResolver; return await resolver(pluginId); } async getExternalBaseUrl(pluginId) { const resolver = this.#externalResolvers.get(pluginId) ?? this.#externalResolvers.get("*") ?? this.#externalFallbackResolver; return await resolver(pluginId); } #updateResolvers(config, defaultEndpoints) { this.#updateFallbackResolvers(config); this.#updatePluginResolvers(config, defaultEndpoints); } #updateFallbackResolvers(config$1) { const backendBaseUrl = lodash.trimEnd(config$1.getString("backend.baseUrl"), "/"); const { listen: { host: listenHost = "::", port: listenPort } } = config.readHttpServerOptions(config$1.getConfig("backend")); const protocol = config$1.has("backend.https") ? "https" : "http"; let host = listenHost; if (host === "::" || host === "") { host = "localhost"; } else if (host === "0.0.0.0") { host = "127.0.0.1"; } if (host.includes(":")) { host = `[${host}]`; } this.#internalFallbackResolver = this.#makeResolver( `${protocol}://${host}:${listenPort}/api/{{pluginId}}`, false ); this.#externalFallbackResolver = this.#makeResolver( `${backendBaseUrl}/api/{{pluginId}}`, false ); } #updatePluginResolvers(config, defaultEndpoints) { const endpoints = defaultEndpoints?.slice() ?? []; const endpointConfigs = config.getOptionalConfigArray( "discovery.endpoints" ); for (const endpointConfig of endpointConfigs ?? []) { if (typeof endpointConfig.get("target") === "string") { endpoints.push({ target: endpointConfig.getString("target"), plugins: endpointConfig.getStringArray("plugins") }); } else { endpoints.push({ target: { internal: endpointConfig.getOptionalString("target.internal"), external: endpointConfig.getOptionalString("target.external") }, plugins: endpointConfig.getStringArray("plugins") }); } } const internalResolvers = /* @__PURE__ */ new Map(); const externalResolvers = /* @__PURE__ */ new Map(); for (const { target, plugins } of endpoints) { let internalResolver; let externalResolver; if (typeof target === "string") { internalResolver = externalResolver = this.#makeResolver(target, false); } else { if (target.internal) { internalResolver = this.#makeResolver(target.internal, true); } if (target.external) { externalResolver = this.#makeResolver(target.external, false); } } if (internalResolver) { for (const pluginId of plugins) { internalResolvers.set(pluginId, internalResolver); } } if (externalResolver) { for (const pluginId of plugins) { externalResolvers.set(pluginId, externalResolver); } } } this.#internalResolvers = internalResolvers; this.#externalResolvers = externalResolvers; } #makeResolver(urlPattern, allowSrv) { const withPluginId = (pluginId, url) => { return url.replace( /\{\{\s*pluginId\s*\}\}/g, encodeURIComponent(pluginId) ); }; if (!this.#srvResolver.isSrvUrl(urlPattern)) { return async (pluginId) => withPluginId(pluginId, urlPattern); } if (!allowSrv) { throw new Error( `SRV resolver URLs cannot be used in the target for external endpoints` ); } const lazyResolvers = /* @__PURE__ */ new Map(); return async (pluginId) => { let lazyResolver = lazyResolvers.get(pluginId); if (!lazyResolver) { lazyResolver = this.#srvResolver.getResolver( withPluginId(pluginId, urlPattern) ); lazyResolvers.set(pluginId, lazyResolver); } return await lazyResolver(); }; } } exports.HostDiscovery = HostDiscovery; //# sourceMappingURL=HostDiscovery.cjs.js.map