core-app-api: extract out overrideBaseUrlConfigs

Co-authored-by: Camila Belo <camilaibs@gmail.com>
Co-authored-by: Philipp Hugenroth <philipph@spotify.com>
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2023-09-08 14:31:47 +02:00
parent 089291c7e5
commit 528b28ffc5
2 changed files with 89 additions and 58 deletions
+5 -58
View File
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import { AppConfig, Config } from '@backstage/config';
import { Config } from '@backstage/config';
import React, {
ComponentType,
PropsWithChildren,
@@ -81,6 +81,7 @@ import { InternalAppContext } from './InternalAppContext';
import { AppRouter, getBasePath } from './AppRouter';
import { AppTranslationProvider } from './AppTranslationProvider';
import { AppTranslationApiImpl } from '../apis/implementations/AppTranslationApi';
import { overrideBaseUrlConfigs } from './overrideBaseUrlConfigs';
type CompatiblePlugin =
| BackstagePlugin
@@ -88,17 +89,6 @@ type CompatiblePlugin =
output(): Array<{ type: 'feature-flag'; name: string }>;
});
/**
* Creates a base URL that uses to the current document origin.
*/
function createLocalBaseUrl(fullUrl: string): string {
const url = new URL(fullUrl);
url.protocol = document.location.protocol;
url.hostname = document.location.hostname;
url.port = document.location.port;
return url.toString().replace(/\/$/, '');
}
function useConfigLoader(
configLoader: AppConfigLoader | undefined,
components: AppComponents,
@@ -131,52 +121,9 @@ function useConfigLoader(
};
}
let configReader;
/**
* config.value can be undefined or empty. If it's either, don't bother overriding anything.
*/
if (config.value?.length) {
const urlConfigReader = ConfigReader.fromConfigs(config.value);
/**
* Test configs may not define `app.baseUrl` or `backend.baseUrl` and we
* don't want to enforce here.
*/
const appBaseUrl = urlConfigReader.getOptionalString('app.baseUrl');
const backendBaseUrl = urlConfigReader.getOptionalString('backend.baseUrl');
let configs = config.value;
const relativeResolverConfig: AppConfig = {
data: {},
context: 'relative-resolver',
};
if (appBaseUrl && backendBaseUrl) {
const appOrigin = new URL(appBaseUrl).origin;
const backendOrigin = new URL(backendBaseUrl).origin;
if (appOrigin === backendOrigin) {
const newBackendBaseUrl = createLocalBaseUrl(backendBaseUrl);
if (backendBaseUrl !== newBackendBaseUrl) {
relativeResolverConfig.data.backend = { baseUrl: newBackendBaseUrl };
}
}
}
if (appBaseUrl) {
const newAppBaseUrl = createLocalBaseUrl(appBaseUrl);
if (appBaseUrl !== newAppBaseUrl) {
relativeResolverConfig.data.app = { baseUrl: newAppBaseUrl };
}
}
/**
* Only add the relative config if there is actually data to add.
*/
if (Object.keys(relativeResolverConfig.data).length) {
configs = configs.concat([relativeResolverConfig]);
}
configReader = ConfigReader.fromConfigs(configs);
} else {
configReader = ConfigReader.fromConfigs([]);
}
const configReader = ConfigReader.fromConfigs(
config.value?.length ? overrideBaseUrlConfigs(config.value) : [],
);
return { api: configReader };
}
@@ -0,0 +1,84 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { AppConfig, ConfigReader } from '@backstage/config';
/**
* Creates a base URL that uses to the current document origin.
*/
function createLocalBaseUrl(fullUrl: string): string {
const url = new URL(fullUrl);
url.protocol = document.location.protocol;
url.hostname = document.location.hostname;
url.port = document.location.port;
return url.toString().replace(/\/$/, '');
}
/**
* If we are able to override the app and backend base URLs to values that
* match the origin of the current location, then this function returns a
* new array of app configs that contain the overrides.
*
* @internal
*/
export function overrideBaseUrlConfigs(inputConfigs: AppConfig[]): AppConfig[] {
const urlConfigReader = ConfigReader.fromConfigs(inputConfigs);
// In tests we may not have `app.baseUrl` or `backend.baseUrl`, to keep them optional
const appBaseUrl = urlConfigReader.getOptionalString('app.baseUrl');
const backendBaseUrl = urlConfigReader.getOptionalString('backend.baseUrl');
let configs = inputConfigs;
let newBackendBaseUrl: string | undefined = undefined;
let newAppBaseUrl: string | undefined = undefined;
if (appBaseUrl && backendBaseUrl) {
const appOrigin = new URL(appBaseUrl).origin;
const backendOrigin = new URL(backendBaseUrl).origin;
if (appOrigin === backendOrigin) {
const maybeNewBackendBaseUrl = createLocalBaseUrl(backendBaseUrl);
if (backendBaseUrl !== maybeNewBackendBaseUrl) {
newBackendBaseUrl = maybeNewBackendBaseUrl;
}
}
}
if (appBaseUrl) {
const maybeNewAppBaseUrl = createLocalBaseUrl(appBaseUrl);
if (appBaseUrl !== maybeNewAppBaseUrl) {
newAppBaseUrl = maybeNewAppBaseUrl;
}
}
// Only add the relative config if there is actually data to add.
if (newAppBaseUrl || newBackendBaseUrl) {
configs = configs.concat({
data: {
app: newAppBaseUrl && {
baseUrl: newAppBaseUrl,
},
backend: newBackendBaseUrl && {
baseUrl: newBackendBaseUrl,
},
},
context: 'relative-resolver',
});
}
return configs;
}