Merge pull request #27457 from backstage/sennyeya/export-http-middleware

feat: export middleware from httpRouter entrypoint
This commit is contained in:
Patrik Oldsberg
2024-11-22 01:29:06 +01:00
committed by GitHub
13 changed files with 148 additions and 8 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-defaults': minor
---
All middleware used by the default `coreServices.http` is now exported for use by custom implementations.
@@ -70,4 +70,67 @@ access the incoming credentials.
## Configuring the service
This service does not have any configuration options.
For more advanced customization, there are several APIs from the `@backstage/backend-defaults/httpRouter` package that allow you to customize the implementation of the config service. The default implementation uses all of the middleware exported from `@backstage/backend-defaults/httpRouter`, including `createLifecycleMiddleware`, `createAuthIntegrationRouter`, `createCredentialsBarrier` and `createCookieAuthRefreshMiddleware`. You can use these to create your own `httpRouter` service implementation, for example - here's how you would add a custom health check route to all plugins:
```ts
import {
createLifecycleMiddleware,
createCookieAuthRefreshMiddleware,
createCredentialsBarrier,
createAuthIntegrationRouter,
} from '@backstage/backend-defaults/httpRouter';
import { createServiceFactory } from '@backstage/backend-plugin-api';
const backend = createBackend();
backend.add(
createServiceFactory({
service: coreServices.httpRouter,
initialization: 'always',
deps: {
plugin: coreServices.pluginMetadata,
config: coreServices.rootConfig,
lifecycle: coreServices.lifecycle,
rootHttpRouter: coreServices.rootHttpRouter,
auth: coreServices.auth,
httpAuth: coreServices.httpAuth,
},
async factory({
auth,
httpAuth,
config,
plugin,
rootHttpRouter,
lifecycle,
}) {
const router = PromiseRouter();
rootHttpRouter.use(`/api/${plugin.getId()}`, router);
const credentialsBarrier = createCredentialsBarrier({
httpAuth,
config,
});
router.use(createAuthIntegrationRouter({ auth }));
router.use(createLifecycleMiddleware({ lifecycle }));
router.use(credentialsBarrier.middleware);
router.use(createCookieAuthRefreshMiddleware({ auth, httpAuth }));
// Add a custom healthcheck endpoint for all plugins.
router.use('/health', (_, res) => {
res.status(200);
});
return {
use(handler: Handler): void {
router.use(handler);
},
addAuthPolicy(policy: HttpRouterServiceAuthPolicy): void {
credentialsBarrier.addAuthPolicy(policy);
},
};
},
}),
);
```
@@ -3,9 +3,45 @@
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
/// <reference types="express" />
import { AuthService } from '@backstage/backend-plugin-api';
import express from 'express';
import { HttpAuthService } from '@backstage/backend-plugin-api';
import { HttpRouterService } from '@backstage/backend-plugin-api';
import { HttpRouterServiceAuthPolicy } from '@backstage/backend-plugin-api';
import { HumanDuration } from '@backstage/types';
import { LifecycleService } from '@backstage/backend-plugin-api';
import { RequestHandler } from 'express';
import { RootConfigService } from '@backstage/backend-plugin-api';
import { Router } from 'express';
import { ServiceFactory } from '@backstage/backend-plugin-api';
// @public (undocumented)
export function createAuthIntegrationRouter(options: {
auth: AuthService;
}): express.Router;
// @public
export function createCookieAuthRefreshMiddleware(options: {
auth: AuthService;
httpAuth: HttpAuthService;
}): Router;
// @public (undocumented)
export function createCredentialsBarrier(options: {
httpAuth: HttpAuthService;
config: RootConfigService;
}): {
middleware: RequestHandler;
addAuthPolicy: (policy: HttpRouterServiceAuthPolicy) => void;
};
// @public
export function createLifecycleMiddleware(
options: LifecycleMiddlewareOptions,
): RequestHandler;
// @public
export const httpRouterServiceFactory: ServiceFactory<
HttpRouterService,
@@ -13,5 +49,12 @@ export const httpRouterServiceFactory: ServiceFactory<
'singleton'
>;
// @public
export interface LifecycleMiddlewareOptions {
// (undocumented)
lifecycle: LifecycleService;
startupRequestPauseTimeout?: HumanDuration;
}
// (No @packageDocumentation comment for this package)
```
@@ -18,6 +18,9 @@ import { AuthService } from '@backstage/backend-plugin-api';
import express from 'express';
import Router from 'express-promise-router';
/**
* @public
*/
export function createAuthIntegrationRouter(options: {
auth: AuthService;
}): express.Router {
@@ -36,6 +36,9 @@ export function createPathPolicyPredicate(policyPath: string) {
};
}
/**
* @public
*/
export function createCredentialsBarrier(options: {
httpAuth: HttpAuthService;
config: RootConfigService;
@@ -15,7 +15,7 @@
*/
import { createLifecycleMiddleware } from './createLifecycleMiddleware';
import { BackendLifecycleImpl } from '../rootLifecycle/rootLifecycleServiceFactory';
import { BackendLifecycleImpl } from '../../rootLifecycle/rootLifecycleServiceFactory';
import { mockServices } from '@backstage/backend-test-utils';
import { ServiceUnavailableError } from '@backstage/errors';
@@ -23,7 +23,7 @@ export const DEFAULT_TIMEOUT = { seconds: 5 };
/**
* Options for {@link createLifecycleMiddleware}.
* @internal
* @public
*/
export interface LifecycleMiddlewareOptions {
lifecycle: LifecycleService;
@@ -47,7 +47,7 @@ export interface LifecycleMiddlewareOptions {
* If the service is shutting down, all requests will be rejected with a
* {@link @backstage/errors#ServiceUnavailableError}.
*
* @internal
* @public
*/
export function createLifecycleMiddleware(
options: LifecycleMiddlewareOptions,
@@ -0,0 +1,20 @@
/*
* Copyright 2024 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.
*/
export { createAuthIntegrationRouter } from './createAuthIntegrationRouter';
export { createCredentialsBarrier } from './createCredentialsBarrier';
export { createLifecycleMiddleware } from './createLifecycleMiddleware';
export type { LifecycleMiddlewareOptions } from './createLifecycleMiddleware';
export { createCookieAuthRefreshMiddleware } from './createCookieAuthRefreshMiddleware';
@@ -21,10 +21,12 @@ import {
createServiceFactory,
HttpRouterServiceAuthPolicy,
} from '@backstage/backend-plugin-api';
import { createLifecycleMiddleware } from './createLifecycleMiddleware';
import { createCredentialsBarrier } from './createCredentialsBarrier';
import { createAuthIntegrationRouter } from './createAuthIntegrationRouter';
import { createCookieAuthRefreshMiddleware } from './createCookieAuthRefreshMiddleware';
import {
createLifecycleMiddleware,
createCookieAuthRefreshMiddleware,
createCredentialsBarrier,
createAuthIntegrationRouter,
} from './http';
/**
* HTTP route registration for plugins.
@@ -15,3 +15,4 @@
*/
export { httpRouterServiceFactory } from './httpRouterServiceFactory';
export * from './http';