backend-app-api: refactor RestrictedIndexedRouter -> DefaultRootHttpRouter
Co-authored-by: Fredrik Adelöw <freben@gmail.com> Co-authored-by: blam <ben@blam.sh> Co-authored-by: Johan Haals <johan.haals@gmail.com> Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -12,6 +12,7 @@ import { CorsOptions } from 'cors';
|
||||
import { ErrorRequestHandler } from 'express';
|
||||
import { Express as Express_2 } from 'express';
|
||||
import { ExtensionPoint } from '@backstage/backend-plugin-api';
|
||||
import { Handler } from 'express';
|
||||
import { HelmetOptions } from 'helmet';
|
||||
import * as http from 'http';
|
||||
import { HttpRouterService } from '@backstage/backend-plugin-api';
|
||||
@@ -79,6 +80,21 @@ export const databaseFactory: (
|
||||
options?: undefined,
|
||||
) => ServiceFactory<PluginDatabaseManager>;
|
||||
|
||||
// @public
|
||||
export class DefaultRootHttpRouter implements RootHttpRouterService {
|
||||
// (undocumented)
|
||||
static create(options?: DefaultRootHttpRouterOptions): DefaultRootHttpRouter;
|
||||
// (undocumented)
|
||||
handler(): Handler;
|
||||
// (undocumented)
|
||||
use(path: string, handler: Handler): void;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface DefaultRootHttpRouterOptions {
|
||||
indexPath?: string | false;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export const discoveryFactory: (
|
||||
options?: undefined,
|
||||
|
||||
+10
-4
@@ -14,9 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { RestrictedIndexedRouter } from './RestrictedIndexedRouter';
|
||||
import { DefaultRootHttpRouter } from './DefaultRootHttpRouter';
|
||||
|
||||
describe('RestrictedIndexedRouter', () => {
|
||||
describe('DefaultRootHttpRouter', () => {
|
||||
it.each([
|
||||
[['/b'], '/a'],
|
||||
[['/a'], '/aa/b'],
|
||||
@@ -25,7 +25,7 @@ describe('RestrictedIndexedRouter', () => {
|
||||
[['/b/a'], '/a'],
|
||||
[['/a'], '/aa'],
|
||||
])(`with existing paths %s, adds %s without conflict`, (existing, added) => {
|
||||
const router = new RestrictedIndexedRouter(false);
|
||||
const router = DefaultRootHttpRouter.create();
|
||||
for (const path of existing) {
|
||||
router.use(path, () => {});
|
||||
}
|
||||
@@ -39,7 +39,7 @@ describe('RestrictedIndexedRouter', () => {
|
||||
])(
|
||||
`find conflict when existing paths %s, adds %s`,
|
||||
(existing, added, conflict) => {
|
||||
const router = new RestrictedIndexedRouter(false);
|
||||
const router = DefaultRootHttpRouter.create();
|
||||
for (const path of existing) {
|
||||
router.use(path, () => {});
|
||||
}
|
||||
@@ -48,4 +48,10 @@ describe('RestrictedIndexedRouter', () => {
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
it('should not be possible to supply an empty indexPath', () => {
|
||||
expect(() => DefaultRootHttpRouter.create({ indexPath: '' })).toThrow(
|
||||
'indexPath option may not be an empty string',
|
||||
);
|
||||
});
|
||||
});
|
||||
+39
-4
@@ -21,18 +21,53 @@ function normalizePath(path: string): string {
|
||||
return path.replace(/\/*$/, '/');
|
||||
}
|
||||
|
||||
export class RestrictedIndexedRouter implements RootHttpRouterService {
|
||||
#indexPath?: false | string;
|
||||
/**
|
||||
* Options for the {@link DefaultRootHttpRouter} class.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface DefaultRootHttpRouterOptions {
|
||||
/**
|
||||
* The path to forward all unmatched requests to. Defaults to '/api/app' if
|
||||
* not given. Disables index path behavior if false is given.
|
||||
*/
|
||||
indexPath?: string | false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default implementation of the {@link @backstage/backend-plugin-api#RootHttpRouterService} interface for
|
||||
* {@link @backstage/backend-plugin-api#coreServices.rootHttpRouter}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export class DefaultRootHttpRouter implements RootHttpRouterService {
|
||||
#indexPath?: string;
|
||||
|
||||
#router = Router();
|
||||
#namedRoutes = Router();
|
||||
#indexRouter = Router();
|
||||
#existingPaths = new Array<string>();
|
||||
|
||||
constructor(indexPath?: false | string) {
|
||||
static create(options?: DefaultRootHttpRouterOptions) {
|
||||
let indexPath;
|
||||
if (options?.indexPath === false) {
|
||||
indexPath = undefined;
|
||||
} else if (options?.indexPath === undefined) {
|
||||
indexPath = '/api/app';
|
||||
} else if (options?.indexPath === '') {
|
||||
throw new Error('indexPath option may not be an empty string');
|
||||
} else {
|
||||
indexPath = options.indexPath;
|
||||
}
|
||||
return new DefaultRootHttpRouter(indexPath);
|
||||
}
|
||||
|
||||
private constructor(indexPath?: string) {
|
||||
this.#indexPath = indexPath;
|
||||
this.#router.use(this.#namedRoutes);
|
||||
this.#router.use(this.#indexRouter);
|
||||
if (this.#indexPath) {
|
||||
this.#router.use(this.#indexRouter);
|
||||
}
|
||||
}
|
||||
|
||||
use(path: string, handler: Handler) {
|
||||
@@ -14,8 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { rootHttpRouterFactory } from './rootHttpRouterFactory';
|
||||
export type {
|
||||
RootHttpRouterFactoryOptions,
|
||||
RootHttpRouterConfigureOptions,
|
||||
export {
|
||||
rootHttpRouterFactory,
|
||||
type RootHttpRouterFactoryOptions,
|
||||
type RootHttpRouterConfigureOptions,
|
||||
} from './rootHttpRouterFactory';
|
||||
export {
|
||||
DefaultRootHttpRouter,
|
||||
type DefaultRootHttpRouterOptions,
|
||||
} from './DefaultRootHttpRouter';
|
||||
|
||||
+4
-4
@@ -27,7 +27,7 @@ import {
|
||||
MiddlewareFactory,
|
||||
readHttpServerOptions,
|
||||
} from '../../../http';
|
||||
import { RestrictedIndexedRouter } from './RestrictedIndexedRouter';
|
||||
import { DefaultRootHttpRouter } from './DefaultRootHttpRouter';
|
||||
|
||||
/**
|
||||
* @public
|
||||
@@ -46,7 +46,8 @@ export interface RootHttpRouterConfigureOptions {
|
||||
*/
|
||||
export type RootHttpRouterFactoryOptions = {
|
||||
/**
|
||||
* The path to forward all unmatched requests to. Defaults to '/api/app'
|
||||
* The path to forward all unmatched requests to. Defaults to '/api/app' if
|
||||
* not given. Disables index path behavior if false is given.
|
||||
*/
|
||||
indexPath?: string | false;
|
||||
|
||||
@@ -82,11 +83,10 @@ export const rootHttpRouterFactory = createServiceFactory({
|
||||
configure = defaultConfigure,
|
||||
}: RootHttpRouterFactoryOptions = {},
|
||||
) {
|
||||
const router = new RestrictedIndexedRouter(indexPath ?? '/api/app');
|
||||
const logger = rootLogger.child({ service: 'rootHttpRouter' });
|
||||
|
||||
const app = express();
|
||||
|
||||
const router = DefaultRootHttpRouter.create({ indexPath });
|
||||
const middleware = MiddlewareFactory.create({ config, logger });
|
||||
|
||||
configure({
|
||||
|
||||
Reference in New Issue
Block a user