2021-08-12 15:04:37 +02:00
|
|
|
import express, { Application, RequestHandler } from 'express';
|
2021-04-22 10:07:10 +02:00
|
|
|
import compression from 'compression';
|
|
|
|
import favicon from 'serve-favicon';
|
|
|
|
import cookieParser from 'cookie-parser';
|
|
|
|
import path from 'path';
|
|
|
|
import errorHandler from 'errorhandler';
|
2021-03-11 22:51:58 +01:00
|
|
|
import { responseTimeMetrics } from './middleware/response-time-metrics';
|
2022-08-19 08:09:44 +02:00
|
|
|
import { corsOriginMiddleware } from './middleware/cors-origin-middleware';
|
2021-03-11 22:51:58 +01:00
|
|
|
import rbacMiddleware from './middleware/rbac-middleware';
|
2021-03-29 19:58:11 +02:00
|
|
|
import apiTokenMiddleware from './middleware/api-token-middleware';
|
2021-04-22 10:07:10 +02:00
|
|
|
import { IUnleashServices } from './types/services';
|
|
|
|
import { IAuthType, IUnleashConfig } from './types/option';
|
|
|
|
import { IUnleashStores } from './types/stores';
|
|
|
|
|
|
|
|
import IndexRouter from './routes';
|
|
|
|
|
|
|
|
import requestLogger from './middleware/request-logger';
|
2021-04-22 10:53:47 +02:00
|
|
|
import demoAuthentication from './middleware/demo-authentication';
|
2021-04-22 10:07:10 +02:00
|
|
|
import ossAuthentication from './middleware/oss-authentication';
|
|
|
|
import noAuthentication from './middleware/no-authentication';
|
|
|
|
import secureHeaders from './middleware/secure-headers';
|
2021-08-12 15:04:37 +02:00
|
|
|
|
2022-01-06 10:31:00 +01:00
|
|
|
import { loadIndexHTML } from './util/load-index-html';
|
2022-08-26 09:25:31 +02:00
|
|
|
import { findPublicFolder } from './util/findPublicFolder';
|
2022-08-26 15:16:29 +02:00
|
|
|
import { conditionalMiddleware } from './middleware/conditional-middleware';
|
2022-09-28 15:53:56 +02:00
|
|
|
import patMiddleware from './middleware/pat-middleware';
|
2022-10-31 10:35:59 +01:00
|
|
|
import { Knex } from 'knex';
|
2022-12-19 08:01:04 +01:00
|
|
|
import maintenanceMiddleware from './middleware/maintenance-middleware';
|
2023-01-26 12:36:45 +01:00
|
|
|
import { unless } from './middleware/unless-middleware';
|
2021-04-22 10:07:10 +02:00
|
|
|
|
2022-01-06 10:31:00 +01:00
|
|
|
export default async function getApp(
|
2021-04-22 10:07:10 +02:00
|
|
|
config: IUnleashConfig,
|
|
|
|
stores: IUnleashStores,
|
|
|
|
services: IUnleashServices,
|
2021-08-12 15:04:37 +02:00
|
|
|
unleashSession?: RequestHandler,
|
2022-10-31 10:35:59 +01:00
|
|
|
db?: Knex,
|
2022-01-06 10:31:00 +01:00
|
|
|
): Promise<Application> {
|
2016-06-18 21:53:18 +02:00
|
|
|
const app = express();
|
2016-11-09 22:31:49 +01:00
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
const baseUriPath = config.server.baseUriPath || '';
|
2022-08-26 09:25:31 +02:00
|
|
|
const publicFolder = findPublicFolder();
|
2022-01-06 10:31:00 +01:00
|
|
|
let indexHTML = await loadIndexHTML(config, publicFolder);
|
2021-04-30 15:31:54 +02:00
|
|
|
|
2020-10-02 16:40:42 +02:00
|
|
|
app.set('trust proxy', true);
|
2017-06-29 11:12:44 +02:00
|
|
|
app.disable('x-powered-by');
|
2021-04-22 10:07:10 +02:00
|
|
|
app.set('port', config.server.port);
|
2016-05-01 18:20:10 +02:00
|
|
|
app.locals.baseUriPath = baseUriPath;
|
2021-12-09 21:02:58 +01:00
|
|
|
if (config.server.serverMetrics && config.eventBus) {
|
2023-01-12 11:26:59 +01:00
|
|
|
app.use(
|
|
|
|
responseTimeMetrics(
|
|
|
|
config.eventBus,
|
|
|
|
config.flagResolver,
|
|
|
|
services.instanceStatsService,
|
|
|
|
),
|
|
|
|
);
|
2021-06-07 10:34:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
app.use(requestLogger(config));
|
|
|
|
|
2016-12-28 21:04:26 +01:00
|
|
|
if (typeof config.preHook === 'function') {
|
2022-10-31 10:35:59 +01:00
|
|
|
config.preHook(app, config, services, db);
|
2016-12-28 21:04:26 +01:00
|
|
|
}
|
|
|
|
|
2018-08-22 17:39:09 +02:00
|
|
|
app.use(compression());
|
2016-05-01 22:59:43 +02:00
|
|
|
app.use(cookieParser());
|
2023-01-26 12:36:45 +01:00
|
|
|
|
|
|
|
app.use(
|
|
|
|
`${baseUriPath}/api/admin/features-batch`,
|
|
|
|
express.json({ strict: false, limit: '500kB' }),
|
|
|
|
);
|
|
|
|
app.use(
|
|
|
|
unless(
|
|
|
|
`${baseUriPath}/api/admin/features-batch`,
|
|
|
|
express.json({ strict: false }),
|
|
|
|
),
|
|
|
|
);
|
2021-08-12 15:04:37 +02:00
|
|
|
if (unleashSession) {
|
|
|
|
app.use(unleashSession);
|
|
|
|
}
|
2020-10-01 21:47:40 +02:00
|
|
|
app.use(secureHeaders(config));
|
2020-09-28 21:54:44 +02:00
|
|
|
app.use(express.urlencoded({ extended: true }));
|
2021-04-22 10:07:10 +02:00
|
|
|
app.use(favicon(path.join(publicFolder, 'favicon.ico')));
|
2022-01-06 10:31:00 +01:00
|
|
|
app.use(baseUriPath, favicon(path.join(publicFolder, 'favicon.ico')));
|
2021-04-30 15:31:54 +02:00
|
|
|
app.use(baseUriPath, express.static(publicFolder, { index: false }));
|
2015-03-10 16:30:56 +01:00
|
|
|
|
2020-12-03 21:09:16 +01:00
|
|
|
if (config.enableOAS) {
|
2021-08-27 12:08:26 +02:00
|
|
|
app.use(`${baseUriPath}/oas`, express.static('docs/api/oas'));
|
2020-12-03 21:09:16 +01:00
|
|
|
}
|
2022-04-25 14:17:59 +02:00
|
|
|
|
|
|
|
if (config.enableOAS && services.openApiService) {
|
|
|
|
services.openApiService.useDocs(app);
|
|
|
|
}
|
|
|
|
|
2022-08-26 15:16:29 +02:00
|
|
|
// Support CORS preflight requests for the frontend endpoints.
|
|
|
|
// Preflight requests should not have Authorization headers,
|
|
|
|
// so this must be handled before the API token middleware.
|
|
|
|
app.options(
|
2022-10-11 09:20:29 +02:00
|
|
|
`${baseUriPath}/api/frontend*`,
|
2022-08-26 15:16:29 +02:00
|
|
|
conditionalMiddleware(
|
|
|
|
() => config.flagResolver.isEnabled('embedProxy'),
|
2022-11-24 16:14:47 +01:00
|
|
|
corsOriginMiddleware(services, config),
|
2022-08-26 15:16:29 +02:00
|
|
|
),
|
|
|
|
);
|
2022-08-19 08:09:44 +02:00
|
|
|
|
2022-09-28 15:53:56 +02:00
|
|
|
app.use(baseUriPath, patMiddleware(config, services));
|
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
switch (config.authentication.type) {
|
|
|
|
case IAuthType.OPEN_SOURCE: {
|
|
|
|
app.use(baseUriPath, apiTokenMiddleware(config, services));
|
2021-08-12 15:04:37 +02:00
|
|
|
ossAuthentication(app, config.server.baseUriPath);
|
2021-04-22 10:07:10 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case IAuthType.ENTERPRISE: {
|
|
|
|
app.use(baseUriPath, apiTokenMiddleware(config, services));
|
|
|
|
config.authentication.customAuthHandler(app, config, services);
|
|
|
|
break;
|
|
|
|
}
|
2021-04-26 21:31:08 +02:00
|
|
|
case IAuthType.HOSTED: {
|
|
|
|
app.use(baseUriPath, apiTokenMiddleware(config, services));
|
|
|
|
config.authentication.customAuthHandler(app, config, services);
|
|
|
|
break;
|
|
|
|
}
|
2021-04-22 10:07:10 +02:00
|
|
|
case IAuthType.DEMO: {
|
2021-05-11 14:15:15 +02:00
|
|
|
app.use(baseUriPath, apiTokenMiddleware(config, services));
|
2021-10-20 13:16:07 +02:00
|
|
|
demoAuthentication(
|
|
|
|
app,
|
|
|
|
config.server.baseUriPath,
|
|
|
|
services,
|
|
|
|
config,
|
|
|
|
);
|
2021-04-22 10:07:10 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case IAuthType.CUSTOM: {
|
|
|
|
app.use(baseUriPath, apiTokenMiddleware(config, services));
|
|
|
|
config.authentication.customAuthHandler(app, config, services);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case IAuthType.NONE: {
|
|
|
|
noAuthentication(baseUriPath, app);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
2021-10-20 13:16:07 +02:00
|
|
|
app.use(baseUriPath, apiTokenMiddleware(config, services));
|
|
|
|
demoAuthentication(
|
|
|
|
app,
|
|
|
|
config.server.baseUriPath,
|
|
|
|
services,
|
|
|
|
config,
|
|
|
|
);
|
2021-04-22 10:07:10 +02:00
|
|
|
break;
|
|
|
|
}
|
2016-12-28 21:04:26 +01:00
|
|
|
}
|
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
app.use(
|
|
|
|
baseUriPath,
|
|
|
|
rbacMiddleware(config, stores, services.accessService),
|
|
|
|
);
|
2021-03-11 22:51:58 +01:00
|
|
|
|
2022-12-21 12:23:44 +01:00
|
|
|
app.use(
|
|
|
|
`${baseUriPath}/api/admin`,
|
|
|
|
conditionalMiddleware(
|
|
|
|
() => config.flagResolver.isEnabled('maintenance'),
|
|
|
|
maintenanceMiddleware(config, services.maintenanceService),
|
|
|
|
),
|
|
|
|
);
|
2022-12-19 08:01:04 +01:00
|
|
|
|
2021-03-29 19:58:11 +02:00
|
|
|
if (typeof config.preRouterHook === 'function') {
|
2022-10-31 10:35:59 +01:00
|
|
|
config.preRouterHook(app, config, services, stores, db);
|
2021-03-29 19:58:11 +02:00
|
|
|
}
|
|
|
|
|
2016-05-01 22:53:09 +02:00
|
|
|
// Setup API routes
|
2020-12-17 19:43:01 +01:00
|
|
|
app.use(`${baseUriPath}/`, new IndexRouter(config, services).router);
|
2014-12-03 15:22:03 +01:00
|
|
|
|
2022-04-25 14:17:59 +02:00
|
|
|
if (services.openApiService) {
|
|
|
|
services.openApiService.useErrorHandler(app);
|
|
|
|
}
|
|
|
|
|
2016-06-18 09:19:57 +02:00
|
|
|
if (process.env.NODE_ENV !== 'production') {
|
2016-11-13 15:31:28 +01:00
|
|
|
app.use(errorHandler());
|
2016-06-18 09:19:57 +02:00
|
|
|
}
|
|
|
|
|
2021-04-30 15:31:54 +02:00
|
|
|
app.get(`${baseUriPath}`, (req, res) => {
|
|
|
|
res.send(indexHTML);
|
|
|
|
});
|
|
|
|
|
2021-04-30 20:16:20 +02:00
|
|
|
app.get(`${baseUriPath}/*`, (req, res) => {
|
2021-05-05 09:01:39 +02:00
|
|
|
if (req.path.startsWith(`${baseUriPath}/api`)) {
|
2022-08-26 15:16:29 +02:00
|
|
|
res.status(404).send({ message: 'Not found' });
|
2021-04-30 20:16:20 +02:00
|
|
|
return;
|
2021-04-30 15:31:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
res.send(indexHTML);
|
|
|
|
});
|
2022-04-25 14:17:59 +02:00
|
|
|
|
2016-05-01 18:20:10 +02:00
|
|
|
return app;
|
2021-04-22 10:07:10 +02:00
|
|
|
}
|