Merge pull request #9225 from RoadieHQ/softer-proxy-startup

allow backend to start if proxy target is not set
This commit is contained in:
Johan Haals
2022-01-31 10:54:41 +01:00
committed by GitHub
3 changed files with 127 additions and 18 deletions
+26
View File
@@ -0,0 +1,26 @@
---
'@backstage/plugin-proxy-backend': patch
---
Adds a new option `skipInvalidTargets` for the proxy `createRouter` which allows the proxy backend to be started with an invalid proxy configuration. If configured, it will simply skip the failed proxy and mount the other valid proxies.
To configure it to pass by failing proxies:
```
const router = await createRouter({
config,
logger,
discovery,
skipInvalidProxies: true,
});
```
If you would like it to fail if a proxy is configured badly:
```
const router = await createRouter({
config,
logger,
discovery,
});
```
@@ -30,23 +30,96 @@ const mockCreateProxyMiddleware = createProxyMiddleware as jest.MockedFunction<
>;
describe('createRouter', () => {
it('works', async () => {
const logger = getVoidLogger();
const config = new ConfigReader({
backend: {
baseUrl: 'https://example.com:7007',
listen: {
port: 7007,
describe('where all proxy config are valid', () => {
it('works', async () => {
const logger = getVoidLogger();
const config = new ConfigReader({
backend: {
baseUrl: 'https://example.com:7007',
listen: {
port: 7007,
},
},
},
proxy: {
'/test': {
target: 'https://example.com',
headers: {
Authorization: 'Bearer supersecret',
},
},
},
});
const discovery = SingleHostDiscovery.fromConfig(config);
const router = await createRouter({
config,
logger,
discovery,
});
expect(router).toBeDefined();
});
const discovery = SingleHostDiscovery.fromConfig(config);
const router = await createRouter({
config,
logger,
discovery,
});
describe('where buildMiddleware would fail', () => {
it('throws an error if skip failures is not set', async () => {
const logger = getVoidLogger();
logger.warn = jest.fn();
const config = new ConfigReader({
backend: {
baseUrl: 'https://example.com:7007',
listen: {
port: 7007,
},
},
// no target would cause the buildMiddleware to fail
proxy: {
'/test': {
headers: {
Authorization: 'Bearer supersecret',
},
},
},
});
const discovery = SingleHostDiscovery.fromConfig(config);
await expect(
createRouter({
config,
logger,
discovery,
}),
).rejects.toThrow(new Error('Proxy target must be a string'));
});
it('works if skip failures is set', async () => {
const logger = getVoidLogger();
logger.warn = jest.fn();
const config = new ConfigReader({
backend: {
baseUrl: 'https://example.com:7007',
listen: {
port: 7007,
},
},
// no target would cause the buildMiddleware to fail
proxy: {
'/test': {
headers: {
Authorization: 'Bearer supersecret',
},
},
},
});
const discovery = SingleHostDiscovery.fromConfig(config);
const router = await createRouter({
config,
logger,
discovery,
skipInvalidProxies: true,
});
expect((logger.warn as jest.Mock).mock.calls[0][0]).toEqual(
'skipped configuring /test due to Proxy target must be a string',
);
expect(router).toBeDefined();
});
expect(router).toBeDefined();
});
});
+14 -4
View File
@@ -51,6 +51,7 @@ export interface RouterOptions {
logger: Logger;
config: Config;
discovery: PluginEndpointDiscovery;
skipInvalidProxies?: boolean;
}
export interface ProxyConfig extends Options {
@@ -185,11 +186,20 @@ export async function createRouter(
const { pathname: pathPrefix } = new URL(externalUrl);
const proxyConfig = options.config.getOptional('proxy') ?? {};
Object.entries(proxyConfig).forEach(([route, proxyRouteConfig]) => {
router.use(
route,
buildMiddleware(pathPrefix, options.logger, route, proxyRouteConfig),
);
try {
router.use(
route,
buildMiddleware(pathPrefix, options.logger, route, proxyRouteConfig),
);
} catch (e) {
if (options.skipInvalidProxies) {
options.logger.warn(`skipped configuring ${route} due to ${e.message}`);
} else {
throw e;
}
}
});
return router;