@backstage/backend-defaults
Version:
Backend defaults used by Backstage backend apps
157 lines (153 loc) • 5.39 kB
JavaScript
;
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