mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-11-27 12:00:35 +03:00
[Status Page] SSR
This commit is contained in:
parent
ffb7ba176c
commit
c095767f4a
6 changed files with 92 additions and 29 deletions
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "uptime-kuma",
|
||||
"version": "1.15.1",
|
||||
"version": "1.16.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "uptime-kuma",
|
||||
"version": "1.15.1",
|
||||
"version": "1.16.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "~1.2.36",
|
||||
|
|
|
@ -1,11 +1,34 @@
|
|||
const { BeanModel } = require("redbean-node/dist/bean-model");
|
||||
const { R } = require("redbean-node");
|
||||
const cheerio = require("cheerio");
|
||||
const { UptimeKumaServer } = require("../uptime-kuma-server");
|
||||
|
||||
class StatusPage extends BeanModel {
|
||||
|
||||
/**
|
||||
* Like this: { "test-uptime.kuma.pet": "default" }
|
||||
* @type {{}}
|
||||
*/
|
||||
static domainMappingList = { };
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Response} response
|
||||
* @param {string} indexHTML
|
||||
* @param {string} slug
|
||||
*/
|
||||
static async handleStatusPageResponse(response, indexHTML, slug) {
|
||||
let statusPage = await R.findOne("status_page", " slug = ? ", [
|
||||
slug
|
||||
]);
|
||||
|
||||
if (statusPage) {
|
||||
response.send(StatusPage.renderHTML(indexHTML, statusPage));
|
||||
} else {
|
||||
response.status(404).send(UptimeKumaServer.getInstance().indexHTML);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SSR for status pages
|
||||
* @param {string} indexHTML
|
||||
|
@ -14,6 +37,17 @@ class StatusPage extends BeanModel {
|
|||
static renderHTML(indexHTML, statusPage) {
|
||||
const $ = cheerio.load(indexHTML);
|
||||
|
||||
$("title").text(statusPage.title);
|
||||
$("meta[name=description]").attr("content", statusPage.description.substring(0, 155));
|
||||
|
||||
if (statusPage.icon) {
|
||||
$("link[rel=icon]")
|
||||
.attr("href", statusPage.icon)
|
||||
.removeAttr("type");
|
||||
}
|
||||
|
||||
const head = $("head");
|
||||
|
||||
return $.root().html();
|
||||
}
|
||||
|
||||
|
|
26
server/routers/status-page-router.js
Normal file
26
server/routers/status-page-router.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
let express = require("express");
|
||||
const apicache = require("../modules/apicache");
|
||||
const { UptimeKumaServer } = require("../uptime-kuma-server");
|
||||
const StatusPage = require("../model/status_page");
|
||||
|
||||
let router = express.Router();
|
||||
|
||||
let cache = apicache.middleware;
|
||||
const server = UptimeKumaServer.getInstance();
|
||||
|
||||
router.get("/status/:slug", cache("5 minutes"), async (request, response) => {
|
||||
let slug = request.params.slug;
|
||||
await StatusPage.handleStatusPageResponse(response, server.indexHTML, slug);
|
||||
});
|
||||
|
||||
router.get("/status", cache("5 minutes"), async (request, response) => {
|
||||
let slug = "default";
|
||||
await StatusPage.handleStatusPageResponse(response, server.indexHTML, slug);
|
||||
});
|
||||
|
||||
router.get("/status-page", cache("5 minutes"), async (request, response) => {
|
||||
let slug = "default";
|
||||
await StatusPage.handleStatusPageResponse(response, server.indexHTML, slug);
|
||||
});
|
||||
|
||||
module.exports = router;
|
|
@ -124,6 +124,7 @@ const TwoFA = require("./2fa");
|
|||
const StatusPage = require("./model/status_page");
|
||||
const { cloudflaredSocketHandler, autoStart: cloudflaredAutoStart, stop: cloudflaredStop } = require("./socket-handlers/cloudflared-socket-handler");
|
||||
const { proxySocketHandler } = require("./socket-handlers/proxy-socket-handler");
|
||||
const apiRouter = require("./routers/api-router");
|
||||
|
||||
app.use(express.json());
|
||||
|
||||
|
@ -148,22 +149,6 @@ let jwtSecret = null;
|
|||
*/
|
||||
let needSetup = false;
|
||||
|
||||
/**
|
||||
* Cache Index HTML
|
||||
* @type {string}
|
||||
*/
|
||||
let indexHTML = "";
|
||||
|
||||
try {
|
||||
indexHTML = fs.readFileSync("./dist/index.html").toString();
|
||||
} catch (e) {
|
||||
// "dist/index.html" is not necessary for development
|
||||
if (process.env.NODE_ENV !== "development") {
|
||||
log.error("server", "Error: Cannot find 'dist/index.html', did you install correctly?");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
(async () => {
|
||||
Database.init(args);
|
||||
await initDatabase(testMode);
|
||||
|
@ -179,14 +164,17 @@ try {
|
|||
|
||||
// Entry Page
|
||||
app.get("/", async (request, response) => {
|
||||
debug(`Request Domain: ${request.hostname}`);
|
||||
log.debug("entry", `Request Domain: ${request.hostname}`);
|
||||
|
||||
if (request.hostname in StatusPage.domainMappingList) {
|
||||
debug("This is a status page domain");
|
||||
// TODO
|
||||
response.send(StatusPage.renderHTML(indexHTML));
|
||||
log.debug("entry", "This is a status page domain");
|
||||
|
||||
let slug = StatusPage.domainMappingList[request.hostname];
|
||||
await StatusPage.handleStatusPageResponse(response, server.indexHTML, slug);
|
||||
|
||||
} else if (exports.entryPage && exports.entryPage.startsWith("statusPage-")) {
|
||||
response.redirect("/status/" + exports.entryPage.replace("statusPage-", ""));
|
||||
|
||||
} else {
|
||||
response.redirect("/dashboard");
|
||||
}
|
||||
|
@ -228,12 +216,16 @@ try {
|
|||
const apiRouter = require("./routers/api-router");
|
||||
app.use(apiRouter);
|
||||
|
||||
// Status Page Router
|
||||
const statusPageRouter = require("./routers/status-page-router");
|
||||
app.use(statusPageRouter);
|
||||
|
||||
// Universal Route Handler, must be at the end of all express routes.
|
||||
app.get("*", async (_request, response) => {
|
||||
if (_request.originalUrl.startsWith("/upload/")) {
|
||||
response.status(404).send("File not found.");
|
||||
} else {
|
||||
response.send(indexHTML);
|
||||
response.send(server.indexHTML);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -29,6 +29,12 @@ class UptimeKumaServer {
|
|||
httpServer = undefined;
|
||||
io = undefined;
|
||||
|
||||
/**
|
||||
* Cache Index HTML
|
||||
* @type {string}
|
||||
*/
|
||||
indexHTML = "";
|
||||
|
||||
static getInstance(args) {
|
||||
if (UptimeKumaServer.instance == null) {
|
||||
UptimeKumaServer.instance = new UptimeKumaServer(args);
|
||||
|
@ -55,6 +61,16 @@ class UptimeKumaServer {
|
|||
this.httpServer = http.createServer(this.app);
|
||||
}
|
||||
|
||||
try {
|
||||
this.indexHTML = fs.readFileSync("./dist/index.html").toString();
|
||||
} catch (e) {
|
||||
// "dist/index.html" is not necessary for development
|
||||
if (process.env.NODE_ENV !== "development") {
|
||||
log.error("server", "Error: Cannot find 'dist/index.html', did you install correctly?");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
this.io = new Server(this.httpServer);
|
||||
}
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@
|
|||
<h1 class="mb-4 title-flex">
|
||||
<!-- Logo -->
|
||||
<span class="logo-wrapper" @click="showImageCropUploadMethod">
|
||||
<img :src="logoURL" alt class="logo me-2" :class="logoClass" @load="statusPageLogoLoaded" />
|
||||
<img :src="logoURL" alt class="logo me-2" :class="logoClass" />
|
||||
<font-awesome-icon v-if="enableEditMode" class="icon-upload" icon="upload" />
|
||||
</span>
|
||||
|
||||
|
@ -687,11 +687,6 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
statusPageLogoLoaded(eventPayload) {
|
||||
// Remark: may not work in dev, due to CORS
|
||||
favicon.image(eventPayload.target);
|
||||
},
|
||||
|
||||
createIncident() {
|
||||
this.enableEditIncidentMode = true;
|
||||
|
||||
|
|
Loading…
Reference in a new issue