Partially change the server core into a class, remove all require("./server") #1520

This commit is contained in:
Louis Lam 2022-04-19 15:38:59 +08:00
parent 1ba92d803e
commit 919393cac9
8 changed files with 110 additions and 70 deletions

View File

@ -3,7 +3,8 @@
*/
const { TimeLogger } = require("../src/util");
const { R } = require("redbean-node");
const { io } = require("./server");
const { UptimeKumaServer } = require("./uptime-kuma-server");
const io = UptimeKumaServer.getInstance().io;
const { setting } = require("./util-server");
const checkVersion = require("./check-version");

View File

@ -3,7 +3,7 @@ const HttpProxyAgent = require("http-proxy-agent");
const HttpsProxyAgent = require("https-proxy-agent");
const SocksProxyAgent = require("socks-proxy-agent");
const { debug } = require("../src/util");
const server = require("./server");
const { UptimeKumaServer } = require("./uptime-kuma-server");
class Proxy {
@ -151,6 +151,8 @@ class Proxy {
* @returns {Promise<void>}
*/
static async reloadProxy() {
const server = UptimeKumaServer.getInstance();
let updatedList = await R.getAssoc("SELECT id, proxy_id FROM monitor");
for (let monitorID in server.monitorList) {

View File

@ -1,15 +1,16 @@
let express = require("express");
const { allowDevAllOrigin, getSettings, setting } = require("../util-server");
const { R } = require("redbean-node");
const server = require("../server");
const apicache = require("../modules/apicache");
const Monitor = require("../model/monitor");
const dayjs = require("dayjs");
const { UP, flipStatus, debug } = require("../../src/util");
const StatusPage = require("../model/status_page");
const { UptimeKumaServer } = require("../uptime-kuma-server");
let router = express.Router();
let cache = apicache.middleware;
const server = UptimeKumaServer.getInstance();
let io = server.io;
router.get("/api/entry-page", async (request, response) => {

View File

@ -1,3 +1,8 @@
/*
* Uptime Kuma Server
* node "server/server.js"
* DO NOT require("./server") in other modules, it likely creates circular dependency!
*/
console.log("Welcome to Uptime Kuma");
// Check Node.js Version
@ -24,14 +29,10 @@ console.log("Node Env: " + process.env.NODE_ENV);
console.log("Importing Node libraries");
const fs = require("fs");
const http = require("http");
const https = require("https");
console.log("Importing 3rd-party libraries");
debug("Importing express");
const express = require("express");
debug("Importing socket.io");
const { Server } = require("socket.io");
debug("Importing redbean-node");
const { R } = require("redbean-node");
debug("Importing jsonwebtoken");
@ -48,26 +49,10 @@ debug("Importing 2FA Modules");
const notp = require("notp");
const base32 = require("thirty-two");
/**
* `module.exports` (alias: `server`) should be inside this class, in order to avoid circular dependency issue.
* @type {UptimeKumaServer}
*/
class UptimeKumaServer {
/**
* Main monitor list
* @type {{}}
*/
monitorList = {};
entryPage = "dashboard";
async sendMonitorList(socket) {
let list = await getMonitorJSONList(socket.userID);
io.to(socket.userID).emit("monitorList", list);
return list;
}
}
const server = module.exports = new UptimeKumaServer();
const { UptimeKumaServer } = require("./uptime-kuma-server");
const server = UptimeKumaServer.getInstance(args);
const io = module.exports.io = server.io;
const app = server.app;
console.log("Importing this project modules");
debug("Importing Monitor");
@ -110,10 +95,6 @@ if (hostname) {
}
const port = parseInt(process.env.UPTIME_KUMA_PORT || process.env.PORT || args.port || 3001);
// SSL
const sslKey = process.env.UPTIME_KUMA_SSL_KEY || process.env.SSL_KEY || args["ssl-key"] || undefined;
const sslCert = process.env.UPTIME_KUMA_SSL_CERT || process.env.SSL_CERT || args["ssl-cert"] || undefined;
const disableFrameSameOrigin = !!process.env.UPTIME_KUMA_DISABLE_FRAME_SAMEORIGIN || args["disable-frame-sameorigin"] || false;
const cloudflaredToken = args["cloudflared-token"] || process.env.UPTIME_KUMA_CLOUDFLARED_TOKEN || undefined;
@ -133,25 +114,6 @@ if (config.demoMode) {
console.log("==== Demo Mode ====");
}
console.log("Creating express and socket.io instance");
const app = express();
let httpServer;
if (sslKey && sslCert) {
console.log("Server Type: HTTPS");
httpServer = https.createServer({
key: fs.readFileSync(sslKey),
cert: fs.readFileSync(sslCert)
}, app);
} else {
console.log("Server Type: HTTP");
httpServer = http.createServer(app);
}
const io = new Server(httpServer);
module.exports.io = io;
// Must be after io instantiation
const { sendNotificationList, sendHeartbeatList, sendImportantHeartbeatList, sendInfo, sendProxyList } = require("./client");
const { statusPageSocketHandler } = require("./socket-handlers/status-page-socket-handler");
@ -1433,12 +1395,12 @@ try {
console.log("Init the server");
httpServer.once("error", async (err) => {
server.httpServer.once("error", async (err) => {
console.error("Cannot listen: " + err.message);
await shutdownFunction();
});
httpServer.listen(port, hostname, () => {
server.httpServer.listen(port, hostname, () => {
if (hostname) {
console.log(`Listening on ${hostname}:${port}`);
} else {
@ -1510,20 +1472,6 @@ async function afterLogin(socket, user) {
}
}
async function getMonitorJSONList(userID) {
let result = {};
let monitorList = await R.find("monitor", " user_id = ? ORDER BY weight DESC, name", [
userID,
]);
for (let monitor of monitorList) {
result[monitor.id] = await monitor.toJSON();
}
return result;
}
async function initDatabase(testMode = false) {
if (! fs.existsSync(Database.path)) {
console.log("Copying Database");
@ -1636,7 +1584,7 @@ function finalFunction() {
console.log("Graceful shutdown successful!");
}
gracefulShutdown(httpServer, {
gracefulShutdown(server.httpServer, {
signals: "SIGINT SIGTERM",
timeout: 30000, // timeout: 30 secs
development: false, // not in dev mode

View File

@ -1,6 +1,7 @@
const { checkLogin, setSetting, setting, doubleCheckPassword } = require("../util-server");
const { CloudflaredTunnel } = require("node-cloudflared-tunnel");
const { io } = require("../server");
const { UptimeKumaServer } = require("../uptime-kuma-server");
const io = UptimeKumaServer.getInstance().io;
const prefix = "cloudflared_";
const cloudflared = new CloudflaredTunnel();

View File

@ -1,7 +1,8 @@
const { checkLogin } = require("../util-server");
const { Proxy } = require("../proxy");
const { sendProxyList } = require("../client");
const server = require("../server");
const { UptimeKumaServer } = require("../uptime-kuma-server");
const server = UptimeKumaServer.getInstance();
module.exports.proxySocketHandler = (socket) => {
socket.on("addProxy", async (proxy, proxyID, callback) => {

View File

@ -6,7 +6,7 @@ const ImageDataURI = require("../image-data-uri");
const Database = require("../database");
const apicache = require("../modules/apicache");
const StatusPage = require("../model/status_page");
const server = require("../server");
const { UptimeKumaServer } = require("../uptime-kuma-server");
module.exports.statusPageSocketHandler = (socket) => {
@ -212,6 +212,8 @@ module.exports.statusPageSocketHandler = (socket) => {
];
await R.exec(`DELETE FROM \`group\` WHERE id NOT IN (${slots}) AND status_page_id = ?`, data);
const server = UptimeKumaServer.getInstance();
// Also change entry page to new slug if it is the default one, and slug is changed.
if (server.entryPage === "statusPage-" + slug && statusPage.slug !== slug) {
server.entryPage = "statusPage-" + statusPage.slug;
@ -281,6 +283,8 @@ module.exports.statusPageSocketHandler = (socket) => {
// Delete a status page
socket.on("deleteStatusPage", async (slug, callback) => {
const server = UptimeKumaServer.getInstance();
try {
checkLogin(socket);

View File

@ -0,0 +1,82 @@
const express = require("express");
const https = require("https");
const fs = require("fs");
const http = require("http");
const { Server } = require("socket.io");
const { R } = require("redbean-node");
/**
* `module.exports` (alias: `server`) should be inside this class, in order to avoid circular dependency issue.
* @type {UptimeKumaServer}
*/
class UptimeKumaServer {
/**
*
* @type {UptimeKumaServer}
*/
static instance = null;
/**
* Main monitor list
* @type {{}}
*/
monitorList = {};
entryPage = "dashboard";
app = undefined;
httpServer = undefined;
io = undefined;
static getInstance(args) {
if (UptimeKumaServer.instance == null) {
UptimeKumaServer.instance = new UptimeKumaServer(args);
}
return UptimeKumaServer.instance;
}
constructor(args) {
// SSL
const sslKey = process.env.UPTIME_KUMA_SSL_KEY || process.env.SSL_KEY || args["ssl-key"] || undefined;
const sslCert = process.env.UPTIME_KUMA_SSL_CERT || process.env.SSL_CERT || args["ssl-cert"] || undefined;
console.log("Creating express and socket.io instance");
this.app = express();
if (sslKey && sslCert) {
console.log("Server Type: HTTPS");
this.httpServer = https.createServer({
key: fs.readFileSync(sslKey),
cert: fs.readFileSync(sslCert)
}, this.app);
} else {
console.log("Server Type: HTTP");
this.httpServer = http.createServer(this.app);
}
this.io = new Server(this.httpServer);
}
async sendMonitorList(socket) {
let list = await this.getMonitorJSONList(socket.userID);
this.io.to(socket.userID).emit("monitorList", list);
return list;
}
async getMonitorJSONList(userID) {
let result = {};
let monitorList = await R.find("monitor", " user_id = ? ORDER BY weight DESC, name", [
userID,
]);
for (let monitor of monitorList) {
result[monitor.id] = await monitor.toJSON();
}
return result;
}
}
module.exports = {
UptimeKumaServer
};