diff --git a/plugins/audit-log-node/README.md b/plugins/audit-log-node/README.md index a3d337d328..dfa8815935 100644 --- a/plugins/audit-log-node/README.md +++ b/plugins/audit-log-node/README.md @@ -61,6 +61,7 @@ import { HttpAuthService, LoggerService, } from '@backstage/backend-plugin-api'; +import { Config } from '@backstage/config'; /* highlight-add-start */ import { DefaultAuditLogger } from '@janus-idp/backstage-plugin-audit-log-node'; @@ -69,6 +70,7 @@ import { DefaultAuditLogger } from '@janus-idp/backstage-plugin-audit-log-node'; export interface RouterOptions { logger: LoggerService; + config: Config; auth: AuthService; httpAuth: HttpAuthService; } @@ -76,7 +78,7 @@ export interface RouterOptions { export async function createRouter( options: RouterOptions, ): Promise { - const { logger, auth, httpAuth } = options; + const { logger, config, auth, httpAuth } = options; /* highlight-add-start */ const auditLogger = new DefaultAuditLogger({ @@ -111,7 +113,10 @@ export async function createRouter( }); /* highlight-add-end */ }); - router.use(errorHandler()); + + const middleware = MiddlewareFactory.create({ logger, config }); + + router.use(middleware.error()); return router; } ``` diff --git a/plugins/kiali-backend/package.json b/plugins/kiali-backend/package.json index 09f8fab5d5..a1fb9257f3 100644 --- a/plugins/kiali-backend/package.json +++ b/plugins/kiali-backend/package.json @@ -46,6 +46,8 @@ "configSchema": "config.d.ts", "dependencies": { "@backstage/backend-common": "^0.23.3", + "@backstage/backend-defaults": "^0.4.1", + "@backstage/backend-dynamic-feature-service": "^0.2.15", "@backstage/backend-plugin-api": "^0.7.0", "@backstage/catalog-client": "^1.6.5", "@backstage/catalog-model": "^1.5.0", @@ -53,7 +55,6 @@ "@backstage/errors": "^1.2.4", "@backstage/plugin-auth-node": "^0.4.17", "@backstage/plugin-catalog-node": "^1.12.4", - "@backstage/backend-dynamic-feature-service": "^0.2.15", "axios": "^1.7.4", "express": "^4.18.2", "express-promise-router": "^4.1.1", @@ -61,6 +62,7 @@ "yn": "^4.0.0" }, "devDependencies": { + "@backstage/backend-test-utils": "^0.4.4", "@backstage/cli": "0.26.11", "@janus-idp/cli": "1.13.1", "@types/express": "4.17.21", diff --git a/plugins/kiali-backend/src/service/router.test.ts b/plugins/kiali-backend/src/service/router.test.ts index 2d92ddec66..d23392af90 100644 --- a/plugins/kiali-backend/src/service/router.test.ts +++ b/plugins/kiali-backend/src/service/router.test.ts @@ -1,4 +1,4 @@ -import { getVoidLogger } from '@backstage/backend-common'; +import { mockServices } from '@backstage/backend-test-utils'; import { ConfigReader } from '@backstage/config'; import express from 'express'; @@ -22,7 +22,7 @@ beforeAll(() => afterEach(() => server.restoreHandlers()); afterAll(() => server.close()); -const logger = getVoidLogger(); +const logger = mockServices.logger.mock(); describe('createRouter', () => { let app: express.Express; diff --git a/plugins/kiali-backend/src/service/router.ts b/plugins/kiali-backend/src/service/router.ts index e1e6747837..86343df495 100644 --- a/plugins/kiali-backend/src/service/router.ts +++ b/plugins/kiali-backend/src/service/router.ts @@ -1,22 +1,30 @@ -import { errorHandler } from '@backstage/backend-common'; +import { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter'; import { LoggerService } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import express from 'express'; import { KialiApiImpl } from '../clients/KialiAPIConnector'; -import { KialiDetails, readKialiConfigs } from './config'; +import { readKialiConfigs } from './config'; export interface RouterOptions { logger: LoggerService; config: Config; } -export const makeRouter = ( - logger: LoggerService, - kialiAPI: KialiApiImpl, - kiali: KialiDetails, -): express.Router => { +/** @public */ +export async function createRouter( + options: RouterOptions, +): Promise { + const { logger } = options; + const { config } = options; + + logger.info('Initializing Kiali backend'); + + const kiali = readKialiConfigs(config); + + const kialiAPI = new KialiApiImpl({ logger, kiali }); + const router = express.Router(); router.use(express.json()); @@ -39,22 +47,8 @@ export const makeRouter = ( res.json(await kialiAPI.status()); }); - router.use(errorHandler()); - return router; -}; - -/** @public */ -export async function createRouter( - options: RouterOptions, -): Promise { - const { logger } = options; - const { config } = options; - - logger.info('Initializing Kiali backend'); - - const kiali = readKialiConfigs(config); + const middleware = MiddlewareFactory.create({ logger, config }); - const kialiAPI = new KialiApiImpl({ logger, kiali }); - - return makeRouter(logger, kialiAPI, kiali); + router.use(middleware.error()); + return router; } diff --git a/plugins/matomo-backend/package.json b/plugins/matomo-backend/package.json index f1409585d5..253242a027 100644 --- a/plugins/matomo-backend/package.json +++ b/plugins/matomo-backend/package.json @@ -46,9 +46,10 @@ }, "dependencies": { "@backstage/backend-common": "^0.23.3", + "@backstage/backend-defaults": "^0.4.1", + "@backstage/backend-dynamic-feature-service": "^0.2.15", "@backstage/backend-plugin-api": "^0.7.0", "@backstage/config": "^1.2.0", - "@backstage/backend-dynamic-feature-service": "^0.2.15", "@types/express": "4.17.20", "express": "^4.18.2", "express-promise-router": "^4.1.1", diff --git a/plugins/matomo-backend/src/plugin.ts b/plugins/matomo-backend/src/plugin.ts index e1c9077943..1e03649f8c 100644 --- a/plugins/matomo-backend/src/plugin.ts +++ b/plugins/matomo-backend/src/plugin.ts @@ -34,6 +34,7 @@ export const matomoBackendPlugin = createBackendPlugin({ logger.info('Matomo plugin is running'); const router = await createRouter({ config, + logger, }); http.use(router); }, diff --git a/plugins/matomo-backend/src/run.ts b/plugins/matomo-backend/src/run.ts deleted file mode 100644 index e48fa22f3f..0000000000 --- a/plugins/matomo-backend/src/run.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { getRootLogger } from '@backstage/backend-common'; - -import yn from 'yn'; - -import { startStandaloneServer } from './service/standaloneServer'; - -const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007; -const enableCors = yn(process.env.PLUGIN_CORS, { default: false }); -const logger = getRootLogger(); - -startStandaloneServer({ port, enableCors, logger }).catch(err => { - logger.error('Standalone server failed:', err); - process.exit(1); -}); - -process.on('SIGINT', () => { - logger.info('CTRL+C pressed; exiting.'); - process.exit(0); -}); diff --git a/plugins/matomo-backend/src/service/router.ts b/plugins/matomo-backend/src/service/router.ts index 12dad1a637..1253464246 100644 --- a/plugins/matomo-backend/src/service/router.ts +++ b/plugins/matomo-backend/src/service/router.ts @@ -1,4 +1,5 @@ -import { errorHandler } from '@backstage/backend-common'; +import { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter'; +import { LoggerService } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import express from 'express'; @@ -6,13 +7,14 @@ import Router from 'express-promise-router'; import { createProxyMiddleware } from 'http-proxy-middleware'; export interface RouterOptions { + logger: LoggerService; config: Config; } export async function createRouter( options: RouterOptions, ): Promise { - const { config } = options; + const { logger, config } = options; const matomoToken = config.getString('matomo.apiToken'); const matomoApiUrl = config.getString('matomo.apiUrl'); @@ -56,6 +58,8 @@ export async function createRouter( }), ); - router.use(errorHandler()); + const middleware = MiddlewareFactory.create({ logger, config }); + + router.use(middleware.error()); return router; } diff --git a/plugins/matomo-backend/src/service/standaloneServer.ts b/plugins/matomo-backend/src/service/standaloneServer.ts deleted file mode 100644 index 693d9e6a93..0000000000 --- a/plugins/matomo-backend/src/service/standaloneServer.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { - createServiceBuilder, - loadBackendConfig, -} from '@backstage/backend-common'; -import { LoggerService } from '@backstage/backend-plugin-api'; - -import { Server } from 'http'; - -import { createRouter } from './router'; - -export interface ServerOptions { - port: number; - enableCors: boolean; - logger: LoggerService; -} - -export async function startStandaloneServer( - options: ServerOptions, -): Promise { - const logger = options.logger.child({ service: 'matomo-backend' }); - const config = await loadBackendConfig({ logger, argv: [] }); - - logger.debug('Starting application server...'); - const router = await createRouter({ - config, - }); - - let service = createServiceBuilder(module) - .setPort(options.port) - .addRouter('/matomo', router); - if (options.enableCors) { - service = service.enableCors({ origin: 'http://localhost:3000' }); - } - - return await service.start().catch(err => { - logger.error('Standalone server failed:', err); - process.exit(1); - }); -} - -module.hot?.accept(); diff --git a/plugins/ocm-backend/package.json b/plugins/ocm-backend/package.json index ebc1bc3db2..524c598d1b 100644 --- a/plugins/ocm-backend/package.json +++ b/plugins/ocm-backend/package.json @@ -49,6 +49,7 @@ "configSchema": "config.d.ts", "dependencies": { "@backstage/backend-common": "^0.23.3", + "@backstage/backend-defaults": "^0.4.1", "@backstage/backend-dynamic-feature-service": "^0.2.15", "@backstage/backend-openapi-utils": "^0.1.15", "@backstage/backend-plugin-api": "^0.7.0", diff --git a/plugins/ocm-backend/src/service/router.ts b/plugins/ocm-backend/src/service/router.ts index 0274e1439e..04e8a7fd32 100644 --- a/plugins/ocm-backend/src/service/router.ts +++ b/plugins/ocm-backend/src/service/router.ts @@ -14,14 +14,12 @@ * limitations under the License. */ -import { - createLegacyAuthAdapters, - errorHandler, - PluginEndpointDiscovery, -} from '@backstage/backend-common'; +import { createLegacyAuthAdapters } from '@backstage/backend-common'; +import { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter'; import { coreServices, createBackendPlugin, + DiscoveryService, HttpAuthService, LoggerService, PermissionsService, @@ -68,7 +66,7 @@ import { ManagedClusterInfo } from '../types'; export interface RouterOptions { logger: LoggerService; config: Config; - discovery: PluginEndpointDiscovery; + discovery: DiscoveryService; permissions: PermissionsService; httpAuth?: HttpAuthService; } @@ -185,7 +183,9 @@ const buildRouter = async ( return response.send(allClusters.flat()); }); - router.use(errorHandler({ logClientErrors: true })); + const middleware = MiddlewareFactory.create({ logger, config }); + + router.use(middleware.error()); return router; }; diff --git a/plugins/orchestrator-backend/package.json b/plugins/orchestrator-backend/package.json index 7ebbc69617..9ea7e67316 100644 --- a/plugins/orchestrator-backend/package.json +++ b/plugins/orchestrator-backend/package.json @@ -70,6 +70,7 @@ "dependencies": { "@backstage/backend-app-api": "^0.8.0", "@backstage/backend-common": "^0.23.3", + "@backstage/backend-defaults": "^0.4.1", "@backstage/backend-dynamic-feature-service": "^0.2.15", "@backstage/backend-plugin-api": "^0.7.0", "@backstage/backend-tasks": "^0.5.27", @@ -108,8 +109,8 @@ "@types/json-schema": "7.0.15" }, "peerDependencies": { - "@janus-idp/backstage-plugin-rbac-common": "1.9.0", - "@janus-idp/backstage-plugin-audit-log-node": "1.4.0" + "@janus-idp/backstage-plugin-audit-log-node": "1.4.0", + "@janus-idp/backstage-plugin-rbac-common": "1.9.0" }, "maintainers": [ "@janus-idp/maintainers-plugins", diff --git a/plugins/orchestrator-backend/src/routerWrapper/index.ts b/plugins/orchestrator-backend/src/routerWrapper/index.ts index 8e13103121..041793e067 100644 --- a/plugins/orchestrator-backend/src/routerWrapper/index.ts +++ b/plugins/orchestrator-backend/src/routerWrapper/index.ts @@ -1,12 +1,13 @@ -import { createLegacyAuthAdapters, UrlReader } from '@backstage/backend-common'; +import { createLegacyAuthAdapters } from '@backstage/backend-common'; import { AuthService, DiscoveryService, HttpAuthService, LoggerService, PermissionsService, + SchedulerService, + UrlReaderService, } from '@backstage/backend-plugin-api'; -import { PluginTaskScheduler } from '@backstage/backend-tasks'; import { CatalogApi } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; @@ -15,19 +16,21 @@ import express from 'express'; import { DevModeService } from '../service/DevModeService'; import { createBackendRouter } from '../service/router'; -export interface RouterArgs { +export interface RouterOptions { config: Config; logger: LoggerService; discovery: DiscoveryService; catalogApi: CatalogApi; - urlReader: UrlReader; - scheduler: PluginTaskScheduler; + urlReader: UrlReaderService; + scheduler: SchedulerService; permissions: PermissionsService; httpAuth?: HttpAuthService; auth?: AuthService; } -export async function createRouter(args: RouterArgs): Promise { +export async function createRouter( + args: RouterOptions, +): Promise { const autoStartDevMode = args.config.getOptionalBoolean( 'orchestrator.sonataFlowService.autoStart', diff --git a/plugins/orchestrator-backend/src/service/router.ts b/plugins/orchestrator-backend/src/service/router.ts index 89bce48e38..665b058590 100644 --- a/plugins/orchestrator-backend/src/service/router.ts +++ b/plugins/orchestrator-backend/src/service/router.ts @@ -1,14 +1,12 @@ -import { - createLegacyAuthAdapters, - errorHandler, - resolvePackagePath, -} from '@backstage/backend-common'; +import { createLegacyAuthAdapters } from '@backstage/backend-common'; +import { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter'; import { HttpAuthService, LoggerService, PermissionsService, + resolvePackagePath, + SchedulerService, } from '@backstage/backend-plugin-api'; -import { PluginTaskScheduler } from '@backstage/backend-tasks'; import { Config } from '@backstage/config'; import { DiscoveryApi } from '@backstage/core-plugin-api'; import { @@ -45,7 +43,7 @@ import { import { UnauthorizedError } from '@janus-idp/backstage-plugin-rbac-common'; import * as pkg from '../../package.json'; -import { RouterArgs } from '../routerWrapper'; +import { RouterOptions } from '../routerWrapper'; import { buildFilter } from '../types/filters'; import { buildPagination } from '../types/pagination'; import { V1 } from './api/v1'; @@ -85,7 +83,7 @@ const authorize = async ( }; export async function createBackendRouter( - args: RouterArgs, + options: RouterOptions, ): Promise { const { config, @@ -95,11 +93,11 @@ export async function createBackendRouter( urlReader, scheduler, permissions, - } = args; + } = options; const { auth, httpAuth } = createLegacyAuthAdapters({ - httpAuth: args.httpAuth, - discovery: args.discovery, - auth: args.auth, + httpAuth: options.httpAuth, + discovery: options.discovery, + auth: options.auth, }); const publicServices = initPublicServices(logger, config, scheduler); @@ -159,14 +157,16 @@ export async function createBackendRouter( routerApi.openApiBackend.handleRequest(req as Request, req, res, next); }); - router.use(errorHandler()); + const middleware = MiddlewareFactory.create({ logger, config }); + + router.use(middleware.error()); return router; } function initPublicServices( logger: LoggerService, config: Config, - scheduler: PluginTaskScheduler, + scheduler: SchedulerService, ): PublicServices { const dataIndexUrl = config.getString('orchestrator.dataIndexService.url'); const dataIndexService = new DataIndexService(dataIndexUrl, logger); diff --git a/plugins/rbac-backend/package.json b/plugins/rbac-backend/package.json index e904808a4f..3a668a07bf 100644 --- a/plugins/rbac-backend/package.json +++ b/plugins/rbac-backend/package.json @@ -32,6 +32,7 @@ }, "dependencies": { "@backstage/backend-common": "^0.23.3", + "@backstage/backend-defaults": "^0.4.1", "@backstage/backend-plugin-api": "^0.7.0", "@backstage/catalog-client": "^1.6.5", "@backstage/catalog-model": "^1.5.0", @@ -40,7 +41,6 @@ "@backstage/errors": "^1.2.4", "@backstage/plugin-auth-node": "^0.4.17", "@backstage/plugin-permission-backend": "^0.5.46", - "@backstage/backend-defaults": "^0.4.1", "@backstage/plugin-permission-common": "^0.8.0", "@backstage/plugin-permission-node": "^0.8.0", "@backstage/types": "^1.1.1", @@ -52,7 +52,6 @@ "chokidar": "^3.6.0", "csv-parse": "^5.5.5", "express": "^4.18.2", - "express-promise-router": "^4.1.1", "js-yaml": "^4.1.0", "knex": "^3.0.0", "lodash": "^4.17.21", diff --git a/plugins/rbac-backend/src/run.ts b/plugins/rbac-backend/src/run.ts deleted file mode 100644 index e48fa22f3f..0000000000 --- a/plugins/rbac-backend/src/run.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { getRootLogger } from '@backstage/backend-common'; - -import yn from 'yn'; - -import { startStandaloneServer } from './service/standaloneServer'; - -const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007; -const enableCors = yn(process.env.PLUGIN_CORS, { default: false }); -const logger = getRootLogger(); - -startStandaloneServer({ port, enableCors, logger }).catch(err => { - logger.error('Standalone server failed:', err); - process.exit(1); -}); - -process.on('SIGINT', () => { - logger.info('CTRL+C pressed; exiting.'); - process.exit(0); -}); diff --git a/plugins/rbac-backend/src/service/router.test.ts b/plugins/rbac-backend/src/service/router.test.ts index 0e13957bc8..2d6714753e 100644 --- a/plugins/rbac-backend/src/service/router.test.ts +++ b/plugins/rbac-backend/src/service/router.test.ts @@ -1,4 +1,4 @@ -import { getVoidLogger } from '@backstage/backend-common'; +import { mockServices } from '@backstage/backend-test-utils'; import express from 'express'; import request from 'supertest'; @@ -10,7 +10,8 @@ describe('createRouter', () => { beforeAll(async () => { const router = await createRouter({ - logger: getVoidLogger(), + logger: mockServices.logger.mock(), + config: mockServices.rootConfig(), }); app = express().use(router); }); diff --git a/plugins/rbac-backend/src/service/router.ts b/plugins/rbac-backend/src/service/router.ts index d3883caead..bddf91d8a9 100644 --- a/plugins/rbac-backend/src/service/router.ts +++ b/plugins/rbac-backend/src/service/router.ts @@ -1,25 +1,29 @@ -import { errorHandler } from '@backstage/backend-common'; +import { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter'; import { LoggerService } from '@backstage/backend-plugin-api'; +import { Config } from '@backstage/config'; import express from 'express'; -import Router from 'express-promise-router'; export interface RouterOptions { logger: LoggerService; + config: Config; } export async function createRouter( options: RouterOptions, ): Promise { - const { logger } = options; + const { logger, config } = options; - const router = Router(); + const router = express.Router(); router.use(express.json()); router.get('/health', (_, response) => { logger.info('PONG!'); response.json({ status: 'ok' }); }); - router.use(errorHandler()); + + const middleware = MiddlewareFactory.create({ logger, config }); + + router.use(middleware.error()); return router; } diff --git a/plugins/rbac-backend/src/service/standaloneServer.ts b/plugins/rbac-backend/src/service/standaloneServer.ts deleted file mode 100644 index bc3c953ad9..0000000000 --- a/plugins/rbac-backend/src/service/standaloneServer.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { createServiceBuilder } from '@backstage/backend-common'; -import { LoggerService } from '@backstage/backend-plugin-api'; - -import { Server } from 'http'; - -import { createRouter } from './router'; - -export interface ServerOptions { - port: number; - enableCors: boolean; - logger: LoggerService; -} - -export async function startStandaloneServer( - options: ServerOptions, -): Promise { - const logger = options.logger.child({ service: 'rbac-backend' }); - logger.debug('Starting application server...'); - const router = await createRouter({ - logger, - }); - - let service = createServiceBuilder(module) - .setPort(options.port) - .addRouter('/rbac', router); - if (options.enableCors) { - service = service.enableCors({ origin: 'http://localhost:3000' }); - } - - return await service.start().catch(err => { - logger.error('Standalone server failed:', err); - process.exit(1); - }); -} - -module.hot?.accept();