backend-app-api: deprecate plugin path configuration and fix /api/* 404

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2024-04-06 15:30:01 +02:00
parent 31ee337a50
commit 10327fb855
6 changed files with 39 additions and 17 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-app-api': patch
---
Deprecate the `getPath` option for the `httpRouterServiceFactory` and more generally the ability to configure plugin API paths to be anything else than `/api/:pluginId/`. Requests towards `/api/*` that do not match an installed plugin will also no longer be handled by the index router, typically instead returning a 404.
@@ -39,20 +39,4 @@ createBackendPlugin({
## Configuring the service
There's additional configuration that you can optionally pass to setup the `httpRouter` core service.
- `getPath` - Can be used to generate a path for each plugin. Currently defaults to `/api/${pluginId}`
You can configure these additional options by adding an override for the core service when calling `createBackend` like follows:
```ts
import { httpRouterServiceFactory } from '@backstage/backend-app-api';
const backend = createBackend();
backend.add(
httpRouterServiceFactory({
getPath: (pluginId: string) => `/plugins/${pluginId}`,
}),
);
```
This service does not have any configuration options.
@@ -7,6 +7,8 @@ description: Documentation for the Root Http Router service
The root HTTP router is a service that allows you to register routes on the root of the backend service. This is useful for things like health checks, or other routes that you want to expose on the root of the backend service. It is used as the base router that backs the `httpRouter` service. Most likely you won't need to use this service directly, but rather use the `httpRouter` service.
The `/api/:pluginId/` path prefix is reserved for use by plugins to register their own routes via the [HttpRouter](./http-router.md) service.
## Using the service
The following example shows how to get the root HTTP router service in your `example` backend plugin to register a health check route.
@@ -74,3 +76,5 @@ backend.add(
}),
);
```
Note that requests towards `/api/*` will always fall through the `routes` if there is no matching plugin route, and never be caught by the configured `indexPath`.
@@ -43,6 +43,7 @@ export const httpRouterServiceFactory = createServiceFactory(
deps: {
plugin: coreServices.pluginMetadata,
config: coreServices.rootConfig,
logger: coreServices.logger,
lifecycle: coreServices.lifecycle,
rootHttpRouter: coreServices.rootHttpRouter,
auth: coreServices.auth,
@@ -52,10 +53,16 @@ export const httpRouterServiceFactory = createServiceFactory(
auth,
httpAuth,
config,
logger,
plugin,
rootHttpRouter,
lifecycle,
}) {
if (options?.getPath) {
logger.warn(
`DEPRECATION WARNING: The 'getPath' option for HttpRouterService is deprecated. The ability to reconfigure the '/api/' path prefix for plugins will be removed in the future.`,
);
}
const getPath = options?.getPath ?? (id => `/api/${id}`);
const path = getPath(plugin.getId());
@@ -89,4 +89,20 @@ describe('DefaultRootHttpRouter', () => {
expect('test').toBe('test');
});
it('should treat unknown /api/ routes as 404', async () => {
const router = DefaultRootHttpRouter.create();
const app = express();
app.use(router.handler());
router.use('/api/app', (_req, res) => res.status(201).end());
router.use('/api/catalog', (_req, res) => res.status(202).end());
await request(app).get('/').expect(201);
await request(app).get('/api/catalog').expect(202);
await request(app).get('/unknown').expect(201);
await request(app).get('/api/unknown').expect(404);
expect('test').toBe('test');
});
});
@@ -66,6 +66,12 @@ export class DefaultRootHttpRouter implements RootHttpRouterService {
private constructor(indexPath?: string) {
this.#indexPath = indexPath;
this.#router.use(this.#namedRoutes);
// Any request with a /api/ prefix will skip the index router, even if no named router matches
this.#router.use('/api/', (_req, _res, next) => {
next('router');
});
if (this.#indexPath) {
this.#router.use(this.#indexRouter);
}