2018-04-21 02:59:30 -03:00
|
|
|
/*****************************************************************************\
|
2024-01-09 17:40:48 -03:00
|
|
|
| █████ █████ ██ █ █████ █████ ████ ██ ████ █████ █████ ███ ® |
|
|
|
|
| ██ █ ███ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
|
|
|
| ██ ███ ████ █ ██ █ ████ █████ ██████ ██ ████ █ █ █ ██ |
|
|
|
|
| ██ ██ █ █ ██ █ █ ██ ██ ██ ██ ██ ██ █ ██ ██ █ █ |
|
|
|
|
| █████ █████ █ ███ █████ ██ ██ ██ ██ █████ ████ █████ █ ███ |
|
2018-04-21 02:59:30 -03:00
|
|
|
| |
|
2024-05-26 20:13:56 -03:00
|
|
|
| General Bots Copyright (c) pragmatismo.cloud. All rights reserved. |
|
2018-04-21 02:59:30 -03:00
|
|
|
| Licensed under the AGPL-3.0. |
|
2018-11-11 19:09:18 -02:00
|
|
|
| |
|
2018-04-21 02:59:30 -03:00
|
|
|
| According to our dual licensing model, this program can be used either |
|
|
|
|
| under the terms of the GNU Affero General Public License, version 3, |
|
|
|
|
| or under a proprietary license. |
|
|
|
|
| |
|
|
|
|
| The texts of the GNU Affero General Public License with an additional |
|
|
|
|
| permission and of our proprietary license can be found at and |
|
|
|
|
| in the LICENSE file you have received along with this program. |
|
|
|
|
| |
|
|
|
|
| This program is distributed in the hope that it will be useful, |
|
2018-09-11 19:40:53 -03:00
|
|
|
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
|
2018-04-21 02:59:30 -03:00
|
|
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
|
|
| GNU Affero General Public License for more details. |
|
|
|
|
| |
|
2024-05-26 20:13:56 -03:00
|
|
|
| "General Bots" is a registered trademark of pragmatismo.cloud. |
|
2018-04-21 02:59:30 -03:00
|
|
|
| The licensing of the program under the AGPLv3 does not imply a |
|
|
|
|
| trademark license. Therefore any rights, title and interest in |
|
|
|
|
| our trademarks remain entirely with us. |
|
|
|
|
| |
|
|
|
|
\*****************************************************************************/
|
|
|
|
|
2018-11-11 19:09:18 -02:00
|
|
|
/**
|
|
|
|
* @fileoverview General Bots server core.
|
|
|
|
*/
|
|
|
|
|
|
|
|
'use strict';
|
2018-09-24 11:04:36 -03:00
|
|
|
|
2024-05-26 20:13:56 -03:00
|
|
|
import { Mutex } from 'async-mutex';
|
|
|
|
import auth from 'basic-auth';
|
2022-11-18 22:39:14 -03:00
|
|
|
import bodyParser from 'body-parser';
|
2024-05-26 20:13:56 -03:00
|
|
|
import { GBLog, GBMinInstance, IGBCoreService, IGBInstance } from 'botlib';
|
|
|
|
import child_process from 'child_process';
|
|
|
|
import express from 'express';
|
2024-09-19 17:46:43 -03:00
|
|
|
import fs from 'fs/promises';
|
2023-07-09 08:46:45 -03:00
|
|
|
import http from 'http';
|
2024-05-26 20:13:56 -03:00
|
|
|
import httpProxy from 'http-proxy';
|
|
|
|
import https from 'https';
|
2022-11-18 22:39:14 -03:00
|
|
|
import mkdirp from 'mkdirp';
|
2024-05-26 20:13:56 -03:00
|
|
|
import { default as Path, default as path } from 'path';
|
2024-01-16 23:32:04 -03:00
|
|
|
import swaggerUI from 'swagger-ui-dist';
|
2022-11-18 22:39:14 -03:00
|
|
|
import { GBAdminService } from '../packages/admin.gbapp/services/GBAdminService.js';
|
|
|
|
import { AzureDeployerService } from '../packages/azuredeployer.gbapp/services/AzureDeployerService.js';
|
|
|
|
import { GBConfigService } from '../packages/core.gbapp/services/GBConfigService.js';
|
|
|
|
import { GBConversationalService } from '../packages/core.gbapp/services/GBConversationalService.js';
|
|
|
|
import { GBCoreService } from '../packages/core.gbapp/services/GBCoreService.js';
|
|
|
|
import { GBDeployer } from '../packages/core.gbapp/services/GBDeployer.js';
|
|
|
|
import { GBImporter } from '../packages/core.gbapp/services/GBImporterService.js';
|
2024-05-26 20:13:56 -03:00
|
|
|
import { GBLogEx } from '../packages/core.gbapp/services/GBLogEx.js';
|
2022-11-18 22:39:14 -03:00
|
|
|
import { GBMinService } from '../packages/core.gbapp/services/GBMinService.js';
|
2023-02-18 16:48:40 -03:00
|
|
|
import { GBSSR } from '../packages/core.gbapp/services/GBSSR.js';
|
2024-05-26 20:13:56 -03:00
|
|
|
import { RootData } from './RootData.js';
|
|
|
|
import { GBUtil } from './util.js';
|
2022-01-23 19:35:20 -03:00
|
|
|
|
2018-04-21 02:59:30 -03:00
|
|
|
/**
|
|
|
|
* General Bots open-core entry point.
|
|
|
|
*/
|
|
|
|
export class GBServer {
|
2019-05-14 23:02:21 -03:00
|
|
|
public static globals: RootData;
|
|
|
|
|
2018-09-24 15:27:26 -03:00
|
|
|
/**
|
|
|
|
* Program entry-point.
|
|
|
|
*/
|
|
|
|
|
2024-09-07 18:13:36 -03:00
|
|
|
public static async run() {
|
2024-04-21 23:39:39 -03:00
|
|
|
GBLogEx.info(0, `The Bot Server is in STARTING mode...`);
|
2019-05-14 23:02:21 -03:00
|
|
|
GBServer.globals = new RootData();
|
2019-06-28 11:17:41 -03:00
|
|
|
GBConfigService.init();
|
2019-03-09 16:59:31 -03:00
|
|
|
const port = GBConfigService.getServerPort();
|
2022-10-28 23:17:35 -03:00
|
|
|
|
2022-11-19 23:34:58 -03:00
|
|
|
if (process.env.TEST_SHELL) {
|
2024-04-21 23:39:39 -03:00
|
|
|
GBLogEx.info(0, `Running TEST_SHELL: ${process.env.TEST_SHELL}...`);
|
2022-11-19 23:34:58 -03:00
|
|
|
try {
|
|
|
|
child_process.execSync(process.env.TEST_SHELL);
|
|
|
|
} catch (error) {
|
|
|
|
GBLog.error(`Running TEST_SHELL ERROR: ${error}...`);
|
2022-11-06 20:19:05 -03:00
|
|
|
}
|
|
|
|
}
|
2023-05-25 21:20:40 -03:00
|
|
|
|
2018-11-12 12:20:44 -02:00
|
|
|
const server = express();
|
2024-01-16 23:32:04 -03:00
|
|
|
this.initEndpointsDocs(server);
|
2024-08-20 15:18:44 -03:00
|
|
|
|
2019-06-05 18:23:31 -03:00
|
|
|
GBServer.globals.server = server;
|
2024-08-19 16:12:23 -03:00
|
|
|
|
2023-02-23 16:44:56 -03:00
|
|
|
GBServer.globals.httpsServer = null;
|
2023-02-15 22:12:24 -03:00
|
|
|
GBServer.globals.webSessions = {};
|
2023-01-13 16:09:45 -03:00
|
|
|
GBServer.globals.processes = {};
|
2023-02-03 12:08:23 -03:00
|
|
|
GBServer.globals.files = {};
|
2019-08-22 17:28:11 -03:00
|
|
|
GBServer.globals.appPackages = [];
|
|
|
|
GBServer.globals.sysPackages = [];
|
|
|
|
GBServer.globals.minInstances = [];
|
2023-10-20 13:39:34 -03:00
|
|
|
GBServer.globals.minBoot = new GBMinInstance();
|
2020-02-25 10:13:38 -03:00
|
|
|
GBServer.globals.wwwroot = null;
|
2020-02-26 15:20:47 -03:00
|
|
|
GBServer.globals.entryPointDialog = null;
|
2022-11-12 21:33:45 -03:00
|
|
|
GBServer.globals.debuggers = [];
|
2024-08-18 17:51:03 -03:00
|
|
|
GBServer.globals.users = [];
|
2023-02-26 06:05:57 -03:00
|
|
|
GBServer.globals.indexSemaphore = new Mutex();
|
2024-09-19 17:46:43 -03:00
|
|
|
|
2019-03-11 19:32:47 -03:00
|
|
|
server.use(bodyParser.json());
|
2023-12-13 10:56:44 -03:00
|
|
|
server.use(bodyParser.json({ limit: '1mb' }));
|
|
|
|
server.use(bodyParser.urlencoded({ limit: '1mb', extended: true }));
|
2024-05-26 20:13:56 -03:00
|
|
|
server.use(function (req, res, next) {
|
|
|
|
for (const key in req.query) {
|
2024-05-06 18:21:18 -03:00
|
|
|
req.query[key.toLowerCase()] = req.query[key];
|
|
|
|
}
|
|
|
|
next();
|
|
|
|
});
|
2023-11-30 22:31:45 -03:00
|
|
|
|
2024-09-19 17:46:43 -03:00
|
|
|
process.on('SIGINT', () => {
|
|
|
|
GBLogEx.info(0, 'SIGINT signal received.');
|
|
|
|
});
|
|
|
|
|
|
|
|
process.on('SIGTSTP', () => {
|
|
|
|
GBLogEx.info(0, 'SIGTSTP signal received.');
|
|
|
|
shutdown();
|
|
|
|
});
|
|
|
|
|
2023-04-01 08:01:10 -03:00
|
|
|
process.on('SIGTERM', () => {
|
2024-04-21 23:39:39 -03:00
|
|
|
GBLogEx.info(0, 'SIGTERM signal received.');
|
2023-04-01 08:01:10 -03:00
|
|
|
});
|
|
|
|
|
2023-12-07 17:10:57 -03:00
|
|
|
process.on('uncaughtException', (err, p) => {
|
2024-08-21 13:09:50 -03:00
|
|
|
GBLogEx.error(0, `GBEXCEPTION: ${GBUtil.toYAML(err)}`);
|
2023-12-07 17:10:57 -03:00
|
|
|
});
|
2024-04-30 20:12:11 -03:00
|
|
|
|
|
|
|
process.on('unhandledRejection', (err, p) => {
|
2024-08-10 12:25:21 -03:00
|
|
|
let bypass = false;
|
|
|
|
let res = err['response'];
|
|
|
|
if (res) {
|
2024-08-18 17:51:03 -03:00
|
|
|
if (res?.body?.error?.message?.startsWith('Failed to send activity: bot timed out')) {
|
|
|
|
bypass = true;
|
2024-08-10 12:25:21 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-18 17:51:03 -03:00
|
|
|
if (!bypass) {
|
2024-08-21 13:09:50 -03:00
|
|
|
GBLogEx.error(0, `GBREJECTION: ${GBUtil.toYAML(err)}`);
|
2024-08-10 12:25:21 -03:00
|
|
|
}
|
2024-05-26 20:13:56 -03:00
|
|
|
});
|
|
|
|
|
|
|
|
// Creates working directory.
|
2019-08-26 13:21:52 -03:00
|
|
|
|
2022-12-12 16:09:49 -03:00
|
|
|
process.env.PWD = process.cwd();
|
2024-09-06 15:30:03 -03:00
|
|
|
const workDir = path.join(process.env.PWD, 'work');
|
2024-09-19 17:46:43 -03:00
|
|
|
if (!(await GBUtil.exists(workDir))) {
|
2019-08-26 13:21:52 -03:00
|
|
|
mkdirp.sync(workDir);
|
2019-10-17 22:32:32 -03:00
|
|
|
}
|
2019-08-26 13:21:52 -03:00
|
|
|
|
2022-01-23 19:35:20 -03:00
|
|
|
const mainCallback = () => {
|
2018-09-09 16:40:04 -03:00
|
|
|
(async () => {
|
|
|
|
try {
|
2024-04-21 23:39:39 -03:00
|
|
|
GBLogEx.info(0, `Now accepting connections on ${port}...`);
|
2024-08-19 23:03:58 -03:00
|
|
|
|
2022-09-04 18:50:36 -03:00
|
|
|
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
|
2018-04-21 02:59:30 -03:00
|
|
|
|
2018-09-09 16:40:04 -03:00
|
|
|
// Reads basic configuration, initialize minimal services.
|
2018-09-09 14:39:37 -03:00
|
|
|
|
2019-03-08 06:37:13 -03:00
|
|
|
const core: IGBCoreService = new GBCoreService();
|
2018-11-27 22:56:11 -02:00
|
|
|
const importer: GBImporter = new GBImporter(core);
|
|
|
|
const deployer: GBDeployer = new GBDeployer(core, importer);
|
2023-07-14 18:45:17 -03:00
|
|
|
let azureDeployer: AzureDeployerService;
|
|
|
|
|
|
|
|
// Ensure that local proxy is setup.
|
2020-04-02 22:02:50 -03:00
|
|
|
|
2023-02-09 19:40:16 -03:00
|
|
|
if (process.env.NODE_ENV === 'development') {
|
2023-02-09 11:31:11 -03:00
|
|
|
const proxy = GBConfigService.get('BOT_URL');
|
2019-06-26 13:18:15 -03:00
|
|
|
if (proxy !== undefined) {
|
|
|
|
GBServer.globals.publicAddress = proxy;
|
2019-10-17 22:32:32 -03:00
|
|
|
} else {
|
2019-06-26 13:18:15 -03:00
|
|
|
GBServer.globals.publicAddress = await core.ensureProxy(port);
|
2023-11-26 16:59:13 -03:00
|
|
|
process.env.BOT_URL = GBServer.globals.publicAddress;
|
2024-04-21 23:39:39 -03:00
|
|
|
GBLogEx.info(0, `Auto-proxy address at: ${process.env.BOT_URL}...`);
|
2019-06-26 13:18:15 -03:00
|
|
|
}
|
2019-05-27 09:14:49 -03:00
|
|
|
} else {
|
2020-04-02 23:52:59 -03:00
|
|
|
const serverAddress = process.env.BOT_URL;
|
2024-04-21 23:39:39 -03:00
|
|
|
GBLogEx.info(0, `.env address at ${serverAddress}...`);
|
2019-05-27 09:14:49 -03:00
|
|
|
GBServer.globals.publicAddress = serverAddress;
|
|
|
|
}
|
2020-07-26 16:46:37 -03:00
|
|
|
|
2019-03-08 06:37:13 -03:00
|
|
|
// Creates a boot instance or load it from storage.
|
2019-02-25 08:36:43 -03:00
|
|
|
|
2023-07-14 18:45:17 -03:00
|
|
|
if (GBConfigService.get('STORAGE_SERVER')) {
|
|
|
|
azureDeployer = await AzureDeployerService.createInstance(deployer);
|
2018-11-28 17:08:06 -02:00
|
|
|
await core.initStorage();
|
2024-08-20 15:13:43 -03:00
|
|
|
} else if (!GBConfigService.get('STORAGE_NAME')) {
|
2024-08-18 17:51:03 -03:00
|
|
|
await core.initStorage();
|
2023-07-14 18:45:17 -03:00
|
|
|
} else {
|
|
|
|
[GBServer.globals.bootInstance, azureDeployer] = await core['createBootInstanceEx'](
|
2022-11-19 23:34:58 -03:00
|
|
|
core,
|
2023-07-14 18:45:17 -03:00
|
|
|
null,
|
|
|
|
GBServer.globals.publicAddress,
|
|
|
|
deployer,
|
|
|
|
GBConfigService.get('FREE_TIER')
|
2022-11-19 23:34:58 -03:00
|
|
|
);
|
2024-08-19 23:03:58 -03:00
|
|
|
await core.saveInstance(GBServer.globals.bootInstance);
|
2018-11-28 17:08:06 -02:00
|
|
|
}
|
|
|
|
|
2018-12-18 13:50:35 -02:00
|
|
|
// Deploys system and user packages.
|
|
|
|
|
2024-04-21 23:39:39 -03:00
|
|
|
GBLogEx.info(0, `Deploying System packages...`);
|
2020-04-13 19:14:55 -03:00
|
|
|
GBServer.globals.sysPackages = await core.loadSysPackages(core);
|
2024-04-21 23:39:39 -03:00
|
|
|
GBLogEx.info(0, `Connecting to Bot Storage...`);
|
2018-11-28 17:08:06 -02:00
|
|
|
await core.checkStorage(azureDeployer);
|
2019-08-22 17:28:11 -03:00
|
|
|
await deployer.deployPackages(core, server, GBServer.globals.appPackages);
|
2021-05-18 10:56:04 -03:00
|
|
|
await core.syncDatabaseStructure();
|
2024-02-18 11:04:07 -03:00
|
|
|
|
2022-01-05 15:27:20 -03:00
|
|
|
// Deployment of local applications for the first time.
|
|
|
|
|
|
|
|
if (GBConfigService.get('DISABLE_WEB') !== 'true') {
|
2024-09-07 18:13:36 -03:00
|
|
|
await deployer.setupDefaultGBUI();
|
2022-01-05 15:27:20 -03:00
|
|
|
}
|
2021-12-20 20:27:02 -03:00
|
|
|
|
2024-04-21 23:39:39 -03:00
|
|
|
GBLogEx.info(0, `Publishing instances...`);
|
2020-12-31 15:36:19 -03:00
|
|
|
const instances: IGBInstance[] = await core.loadAllInstances(
|
2020-10-23 09:55:44 -03:00
|
|
|
core,
|
|
|
|
azureDeployer,
|
|
|
|
GBServer.globals.publicAddress
|
2018-11-28 17:08:06 -02:00
|
|
|
);
|
2020-10-26 20:18:38 -03:00
|
|
|
|
2024-08-20 15:18:44 -03:00
|
|
|
if (instances.length === 0) {
|
2024-08-20 15:13:43 -03:00
|
|
|
if (GBConfigService.get('STORAGE_NAME')) {
|
2024-08-19 23:03:58 -03:00
|
|
|
const instance = await importer.importIfNotExistsBotPackage(
|
|
|
|
GBConfigService.get('BOT_ID'),
|
|
|
|
'boot.gbot',
|
|
|
|
'packages/boot.gbot',
|
|
|
|
GBServer.globals.bootInstance
|
|
|
|
);
|
2023-11-30 22:31:45 -03:00
|
|
|
|
2024-08-19 23:03:58 -03:00
|
|
|
instances.push(instance);
|
|
|
|
GBServer.globals.minBoot.instance = instances[0];
|
|
|
|
GBServer.globals.bootInstance = instances[0];
|
|
|
|
await deployer.deployBotOnAzure(instance, GBServer.globals.publicAddress);
|
2021-04-17 17:20:44 -03:00
|
|
|
|
2024-08-19 23:03:58 -03:00
|
|
|
// Runs the search even with empty content to create structure.
|
2021-11-29 18:39:42 -03:00
|
|
|
|
2024-08-19 23:03:58 -03:00
|
|
|
await azureDeployer['runSearch'](instance);
|
|
|
|
}
|
2020-10-26 20:18:38 -03:00
|
|
|
}
|
|
|
|
|
2024-08-21 13:09:50 -03:00
|
|
|
const conversationalService: GBConversationalService = new GBConversationalService(core);
|
|
|
|
const adminService: GBAdminService = new GBAdminService(core);
|
|
|
|
const minService: GBMinService = new GBMinService(core, conversationalService, adminService, deployer);
|
|
|
|
GBServer.globals.minService = minService;
|
|
|
|
|
|
|
|
// Just sync if not using LOAD_ONLY.
|
|
|
|
|
|
|
|
if (!GBConfigService.get('STORAGE_NAME') && !process.env.LOAD_ONLY) {
|
2024-08-20 15:18:44 -03:00
|
|
|
await core['ensureFolders'](instances, deployer);
|
|
|
|
}
|
2020-10-23 09:55:44 -03:00
|
|
|
GBServer.globals.bootInstance = instances[0];
|
2018-11-27 22:56:11 -02:00
|
|
|
|
2018-12-18 13:50:35 -02:00
|
|
|
// Builds minimal service infrastructure.
|
2020-04-02 22:02:50 -03:00
|
|
|
|
2024-08-30 14:15:02 -03:00
|
|
|
const minInstances = await minService.buildMin(instances);
|
|
|
|
|
|
|
|
GBServer.globals.webDavServer = await GBCoreService.createWebDavServer(minInstances);
|
2024-08-19 23:03:58 -03:00
|
|
|
|
2024-10-19 12:52:57 -03:00
|
|
|
// Parse the ROUTE from the .env file
|
2024-10-19 13:01:53 -03:00
|
|
|
const routeConfig = process.env.ROUTER.split(';').reduce((acc, entry) => {
|
2024-10-19 12:52:57 -03:00
|
|
|
const [domain, port] = entry.split(':');
|
|
|
|
acc[domain] = port;
|
|
|
|
return acc;
|
|
|
|
}, {});
|
|
|
|
|
|
|
|
// Proxy setup
|
|
|
|
const proxy = httpProxy.createProxyServer({});
|
|
|
|
|
2024-04-17 13:24:55 -03:00
|
|
|
server.all('*', async (req, res, next) => {
|
2024-10-19 12:52:57 -03:00
|
|
|
const host = req.headers.host.startsWith('www.') ? req.headers.host.substring(4) : req.headers.host;
|
|
|
|
|
|
|
|
// Check if the request is for logs
|
2023-03-27 10:07:28 -03:00
|
|
|
if (req.originalUrl.startsWith('/logs')) {
|
2024-05-26 20:13:56 -03:00
|
|
|
if (process.env.ENABLE_WEBLOG === 'true') {
|
2023-03-27 10:07:28 -03:00
|
|
|
const admins = {
|
|
|
|
admin: { password: process.env.ADMIN_PASS }
|
|
|
|
};
|
2024-10-19 12:52:57 -03:00
|
|
|
|
|
|
|
// Authenticate the user
|
2022-11-19 23:34:58 -03:00
|
|
|
const user = auth(req);
|
2022-08-07 11:05:20 -03:00
|
|
|
if (!user || !admins[user.name] || admins[user.name].password !== user.pass) {
|
|
|
|
res.set('WWW-Authenticate', 'Basic realm="example"');
|
|
|
|
return res.status(401).send();
|
|
|
|
}
|
2022-10-28 23:17:35 -03:00
|
|
|
} else {
|
2024-10-19 12:52:57 -03:00
|
|
|
// If logging is not enabled, pass the request to GBSSR filter
|
2023-03-27 10:07:28 -03:00
|
|
|
await GBSSR.ssrFilter(req, res, next);
|
2022-08-06 19:38:13 -03:00
|
|
|
}
|
2023-03-27 10:07:28 -03:00
|
|
|
} else {
|
2024-10-19 13:55:57 -03:00
|
|
|
GBLogEx.info(0, `Host request: ${host}`);
|
|
|
|
|
2024-10-19 12:52:57 -03:00
|
|
|
// If the domain is in routeConfig, proxy to the corresponding local service
|
|
|
|
if (routeConfig[host]) {
|
|
|
|
const target = `http://localhost:${routeConfig[host]}`;
|
2024-10-19 13:55:57 -03:00
|
|
|
GBLogEx.info(0, `Routing to internal server: ${target}`);
|
2024-10-19 12:52:57 -03:00
|
|
|
return proxy.web(req, res, { target }, (err) => {
|
2024-10-19 13:55:57 -03:00
|
|
|
GBLogEx.error(0, `GBRouter error: ${GBUtil.toYAML(err)}`);
|
2024-10-19 12:52:57 -03:00
|
|
|
res.status(500).send('Internal proxy error.');
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the host is the API host, redirect traffic to the API
|
2024-04-17 13:24:55 -03:00
|
|
|
if (host === process.env.API_HOST) {
|
2024-10-19 12:52:57 -03:00
|
|
|
console.log('Redirecting to API...');
|
|
|
|
return proxy.web(req, res, { target: 'http://localhost:1111' }); // Express API server
|
2024-04-17 13:24:55 -03:00
|
|
|
}
|
2024-10-19 12:52:57 -03:00
|
|
|
|
|
|
|
// For other cases, pass through the GBSSR filter
|
|
|
|
await GBSSR.ssrFilter(req, res, next);
|
2023-03-27 10:07:28 -03:00
|
|
|
}
|
2023-02-09 19:40:16 -03:00
|
|
|
});
|
2024-10-19 12:52:57 -03:00
|
|
|
|
2024-04-21 23:39:39 -03:00
|
|
|
GBLogEx.info(0, `The Bot Server is in RUNNING mode...`);
|
2022-10-28 23:17:35 -03:00
|
|
|
|
2024-08-21 13:09:50 -03:00
|
|
|
await minService.startSimpleTest(GBServer.globals.minBoot);
|
|
|
|
|
2018-12-18 13:50:35 -02:00
|
|
|
// Opens Navigator.
|
|
|
|
|
2023-01-01 14:24:53 -03:00
|
|
|
if (process.env.DEV_OPEN_BROWSER) {
|
|
|
|
core.openBrowserInDevelopment();
|
|
|
|
}
|
2024-09-15 16:30:03 -03:00
|
|
|
} catch (error) {
|
|
|
|
GBLog.error(`STOP: ${GBUtil.toYAML(error.message)}`);
|
2024-09-19 17:46:43 -03:00
|
|
|
shutdown();
|
2018-09-09 16:40:04 -03:00
|
|
|
}
|
2018-09-24 11:04:36 -03:00
|
|
|
})();
|
2022-01-23 19:35:20 -03:00
|
|
|
};
|
2022-12-16 10:36:09 -03:00
|
|
|
|
2024-04-17 12:39:50 -03:00
|
|
|
if (process.env.CERTIFICATE_PFX) {
|
2024-10-19 13:01:53 -03:00
|
|
|
let routeConfig ={};
|
|
|
|
if (process.env.ROUTER){
|
2024-10-19 12:52:57 -03:00
|
|
|
// Parse the ROUTE from the .env file
|
2024-10-19 13:01:53 -03:00
|
|
|
routeConfig = process.env.ROUTER.split(';').reduce((acc, entry) => {
|
2024-10-19 12:52:57 -03:00
|
|
|
const [domain, port] = entry.split(':');
|
|
|
|
acc[domain] = port;
|
|
|
|
return acc;
|
|
|
|
}, {});
|
2024-10-19 13:01:53 -03:00
|
|
|
}
|
2024-10-19 12:52:57 -03:00
|
|
|
|
|
|
|
// Create a proxy server for internal routing
|
|
|
|
const proxy = httpProxy.createProxyServer();
|
|
|
|
|
|
|
|
const server1 = http.createServer(async (req, res) => {
|
|
|
|
let host = req.headers.host.startsWith('www.') ? req.headers.host.substring(4) : req.headers.host;
|
|
|
|
|
|
|
|
// If the domain is in the routeConfig, handle internally
|
|
|
|
if (routeConfig[host]) {
|
|
|
|
const target = `http://localhost:${routeConfig[host]}`;
|
|
|
|
proxy.web(req, res, { target }, (err) => {
|
|
|
|
console.error('Internal routing error:', err);
|
|
|
|
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
|
|
res.end('Internal routing error.');
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
// Otherwise, redirect to the HTTPS version
|
|
|
|
res.writeHead(301, {
|
|
|
|
Location: `https://${host}${req.url}`
|
|
|
|
}).end();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
server1.listen(80, () => {
|
|
|
|
console.log('HTTP Server is listening on port 80');
|
2024-04-17 12:36:03 -03:00
|
|
|
});
|
|
|
|
|
|
|
|
const options1 = {
|
|
|
|
passphrase: process.env.CERTIFICATE_PASSPHRASE,
|
2024-09-07 18:13:36 -03:00
|
|
|
pfx: await fs.readFile(process.env.CERTIFICATE_PFX),
|
2024-09-19 17:46:43 -03:00
|
|
|
ca: (await GBUtil.exists(process.env.CERTIFICATE_CA)) ? await fs.readFile(process.env.CERTIFICATE_CA) : null
|
2024-04-17 12:36:03 -03:00
|
|
|
};
|
|
|
|
|
|
|
|
const httpsServer = https.createServer(options1, server).listen(port, mainCallback);
|
|
|
|
GBServer.globals.httpsServer = httpsServer;
|
|
|
|
|
|
|
|
for (let i = 2; ; i++) {
|
|
|
|
const certPfxEnv = `CERTIFICATE${i}_PFX`;
|
|
|
|
const certPassphraseEnv = `CERTIFICATE${i}_PASSPHRASE`;
|
|
|
|
const certDomainEnv = `CERTIFICATE${i}_DOMAIN`;
|
|
|
|
|
|
|
|
if (process.env[certPfxEnv] && process.env[certPassphraseEnv] && process.env[certDomainEnv]) {
|
|
|
|
const options = {
|
|
|
|
passphrase: process.env[certPassphraseEnv],
|
2024-09-07 18:13:36 -03:00
|
|
|
pfx: await fs.readFile(process.env[certPfxEnv])
|
2024-04-17 12:36:03 -03:00
|
|
|
};
|
|
|
|
httpsServer.addContext(process.env[certDomainEnv], options);
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2024-05-26 20:13:56 -03:00
|
|
|
} else {
|
2024-04-17 12:36:03 -03:00
|
|
|
server.listen(port, mainCallback);
|
|
|
|
}
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
2024-01-16 23:32:04 -03:00
|
|
|
|
|
|
|
public static initEndpointsDocs(app: express.Application) {
|
|
|
|
const ENDPOINT = '/docs';
|
|
|
|
const SWAGGER_FILE_NAME = 'swagger.yaml';
|
|
|
|
const swaggerUiAssetPath = swaggerUI.getAbsoluteFSPath();
|
|
|
|
|
|
|
|
// A workaround for swagger-ui-dist not being able to set custom swagger URL
|
|
|
|
const indexContent = fs
|
2024-09-07 18:13:36 -03:00
|
|
|
.readFile(path.join(swaggerUiAssetPath, 'swagger-initializer.js'))
|
2024-02-18 11:04:07 -03:00
|
|
|
.toString()
|
|
|
|
.replace('https://petstore.swagger.io/v2/swagger.json', `/${SWAGGER_FILE_NAME}`);
|
2024-01-16 23:32:04 -03:00
|
|
|
app.get(`${ENDPOINT}/swagger-initializer.js`, (req, res) => res.send(indexContent));
|
|
|
|
|
|
|
|
// Serve the swagger-ui assets
|
|
|
|
app.use(ENDPOINT, express.static(swaggerUiAssetPath));
|
|
|
|
|
|
|
|
// Serve the swagger file
|
|
|
|
app.get(`/${SWAGGER_FILE_NAME}`, (req, res) => {
|
2024-02-18 11:04:07 -03:00
|
|
|
res.sendFile(path.join(process.env.PWD, SWAGGER_FILE_NAME));
|
2024-01-16 23:32:04 -03:00
|
|
|
});
|
2024-02-18 11:04:07 -03:00
|
|
|
}
|
2018-04-21 02:59:30 -03:00
|
|
|
}
|
2024-09-19 17:46:43 -03:00
|
|
|
|
|
|
|
function shutdown() {
|
|
|
|
GBServer.globals.server.close(() => {
|
|
|
|
GBLogEx.info(0, 'General Bots server closed.');
|
|
|
|
|
|
|
|
GBServer.globals.apiServer.close(() => {
|
|
|
|
GBLogEx.info(0, 'General Bots API server closed.');
|
|
|
|
process.exit(0);
|
|
|
|
});
|
2024-09-24 14:30:01 -03:00
|
|
|
|
2024-09-19 17:46:43 -03:00
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|