From 92909e4ab7043fbf331cae24c93cf94cee6b8e63 Mon Sep 17 00:00:00 2001 From: 00Fjongl <65314359+00Fjongl@users.noreply.github.com> Date: Wed, 7 Aug 2024 10:10:19 -0500 Subject: [PATCH] New shutdown script for cross-platform ease of use; implement host option in config file; minor code cleanup. --- .gitignore | 1 + package.json | 4 ++-- read-config.mjs | 6 ++++++ shutdown.mjs | 21 +++++++++++++++++++++ src/config.json | 1 + src/routes.mjs | 1 + src/server.mjs | 35 +++++++++++++++++++++++++++-------- 7 files changed, 59 insertions(+), 10 deletions(-) create mode 100644 shutdown.mjs diff --git a/.gitignore b/.gitignore index fccaf25e..6deb341f 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ debug.log /lib/rammerhead/cache-js/* !/lib/rammerhead/cache-js/.gitignore /views/dist/* +/src/.shutdown diff --git a/package.json b/package.json index c0b5ad5f..2a00d45b 100644 --- a/package.json +++ b/package.json @@ -7,10 +7,10 @@ "scripts": { "start": "npm install && npm run build && npm run manual-start", "restart": "npm stop; npm run manual-start", - "stop": "pm2 stop ecosystem.config.js; pkill node || true", + "stop": "( pm2 stop ecosystem.config.js ) ; node shutdown.mjs", "test": "npm run proxy-validator", "monit": "pm2 monit", - "manual-start": "node ./read-config.mjs 'production' && ( pm2 start ecosystem.config.js --env production ) || ( node backend.js & pkill -n npm || true )", + "manual-start": "node read-config.mjs 'production' && ( pm2 start ecosystem.config.js --env production ) || ( node backend.js & pkill -n npm || true )", "build": "sh ./build-assets.sh && cd lib/rammerhead && npm install && npm run build", "start-test-server": "timeout 5 node backend.js; test $? -eq 124 && ( npm run manual-start & ) || exit 1", "proxy-validator": "node proxyServiceValidator.js" diff --git a/read-config.mjs b/read-config.mjs index a86257f8..e7723672 100644 --- a/read-config.mjs +++ b/read-config.mjs @@ -1,7 +1,13 @@ import { readFile } from 'node:fs/promises'; + +// Parse the config file to grab a property value from it. let property = JSON.parse(await readFile(new URL("./src/config.json", import.meta.url))); +// Combine all descriptors (from command line arguments) to get the property value. process.argv.slice(2).forEach(descriptor => {property = property[descriptor]}); + +// Return a boolean if it's true or false. if (typeof property === "boolean") process.exitCode = +!property; +// Otherwise, return a stringified version to the stream. else { console.log(property); process.exitCode = 0; diff --git a/shutdown.mjs b/shutdown.mjs new file mode 100644 index 00000000..1a399f20 --- /dev/null +++ b/shutdown.mjs @@ -0,0 +1,21 @@ +import { readFile, writeFile, unlink } from 'node:fs/promises'; + +const config = Object.freeze(JSON.parse(await readFile(new URL("./src/config.json", import.meta.url)))); + +const serverUrl = (base => { + try { + base = new URL(config.host); + } catch (e) { + base = new URL("http://a"); + base.host = config.host; + } + base.port = process.env.PORT || config.port; + return Object.freeze(base); +})(); + +const shutdown = new URL("./src/.shutdown", import.meta.url); + +await writeFile(shutdown, ""); +try {await fetch(new URL("/test-shutdown", serverUrl))} +catch (e) {await unlink(shutdown)} +process.exitCode = 0; diff --git a/src/config.json b/src/config.json index 6a19f4fe..438a7924 100644 --- a/src/config.json +++ b/src/config.json @@ -1,5 +1,6 @@ { "title": "HU LTS", + "host": "0.0.0.0", "port": "8080", "minifyScripts": true, "production": false diff --git a/src/routes.mjs b/src/routes.mjs index 281c3591..9ca7839f 100644 --- a/src/routes.mjs +++ b/src/routes.mjs @@ -15,6 +15,7 @@ const text404 = readFileSync( const pages = { index: "index.html", + "manifest.json": "manifest.json", /* Main */ documentation: "docs.html", questions: "faq.html", diff --git a/src/server.mjs b/src/server.mjs index 7598aa61..3fbd3d6f 100644 --- a/src/server.mjs +++ b/src/server.mjs @@ -15,10 +15,22 @@ import path from 'node:path'; import { paintSource, tryReadFile } from './randomization.mjs'; import loadTemplates from './templates.mjs'; import { fileURLToPath } from 'node:url'; -import { existsSync } from 'node:fs'; +import { existsSync, unlinkSync } from 'node:fs'; const config = Object.freeze(JSON.parse(await readFile(new URL("./config.json", import.meta.url)))), { pages, text404 } = pkg; const __dirname = path.resolve(); -const port = process.env.PORT || config.port; +const serverUrl = (base => { + try { + base = new URL(config.host); + } catch (e) { + base = new URL("http://a"); + base.host = config.host; + } + base.port = process.env.PORT || config.port; + return Object.freeze(base); +})(); +console.log(serverUrl); + +const shutdown = fileURLToPath(new URL("./.shutdown", import.meta.url)); const rh = createRammerhead(); const rammerheadScopes = [ @@ -40,7 +52,7 @@ const rammerheadScopes = [ ]; const rammerheadSession = /^\/[a-z0-9]{32}/; const shouldRouteRh = req => { - const url = new URL(req.url, "http://0.0.0.0"); + const url = new URL(req.url, serverUrl); return ( rammerheadScopes.includes(url.pathname) || rammerheadSession.test(url.pathname) @@ -130,7 +142,7 @@ app.register(fastifyStatic, { app.register(fastifyStatic, { root: epoxyPath, prefix: "/epoxy/", - decorateReply: false + decorateReply: false }); app.register(fastifyStatic, { root: libcurlPath, @@ -140,12 +152,12 @@ app.register(fastifyStatic, { app.register(fastifyStatic, { root: bareModulePath, prefix: "/bareasmodule/", - decorateReply: false + decorateReply: false }); app.register(fastifyStatic, { root: baremuxPath, prefix: "/baremux/", - decorateReply: false + decorateReply: false }); @@ -155,6 +167,13 @@ app.register(fastifyStatic, { // back here. Which path converts to what is defined in routes.mjs. app.get("/:file", (req, reply) => { + if (req.params.file === "test-shutdown" && existsSync(shutdown)) { + console.log("Holy Unblocker is shutting down."); + app.close(); + unlinkSync(shutdown); + process.exitCode = 0; + } + // Testing for future features that need cookies to deliver alternate source files. if (req.raw.rawHeaders.includes("Cookie")) console.log(req.raw.rawHeaders[req.raw.rawHeaders.indexOf("Cookie") + 1]); @@ -200,5 +219,5 @@ app.setNotFoundHandler((req, reply) => { // Configure host to your liking, but remember to tweak the Rammerhead IP // as well above for any changes. -app.listen({ port: port /*, host: '0.0.0.0' */}); -console.log("Holy Unblocker is listening on port " + port + "."); +app.listen({ port: serverUrl.port, host: serverUrl.hostname }); +console.log("Holy Unblocker is listening on port " + serverUrl.port + ".");