diff --git a/backend.js b/backend.js
index 0062b594..1973b5ce 100644
--- a/backend.js
+++ b/backend.js
@@ -1,3 +1,3 @@
(async () => {
- await import("./src/server.mjs");
+ await import("./src/fastify.mjs");
})();
diff --git a/package.json b/package.json
index 01b17c6e..e8506188 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,8 @@
"author": "Titanium Network",
"license": "GNU AFFERO",
"dependencies": {
+ "@fastify/helmet": "^11.1.1",
+ "@fastify/static": "^7.0.4",
"@mercuryworkshop/bare-as-module3": "^2.2.2",
"@mercuryworkshop/bare-mux": "^2.0.1",
"@mercuryworkshop/epoxy-transport": "^2.1.3",
@@ -27,6 +29,7 @@
"@tomphttp/bare-server-node": "^2.0.3",
"axios": "^1.7.2",
"express": "^4.19.2",
+ "fastify": "^4.28.1",
"helmet": "^7.1.0",
"mime-types": "^2.1.35",
"puppeteer": "^22.12.1",
diff --git a/src/fastify.mjs b/src/fastify.mjs
new file mode 100644
index 00000000..9b9fad37
--- /dev/null
+++ b/src/fastify.mjs
@@ -0,0 +1,114 @@
+import Fastify from 'fastify';
+import { createServer } from 'node:http';
+import wisp from 'wisp-server-node';
+import createRammerhead from "rammerhead/src/server/index.js";
+import { epoxyPath } from "@mercuryworkshop/epoxy-transport";
+import { libcurlPath } from "@mercuryworkshop/libcurl-transport";
+import { bareModulePath } from "@mercuryworkshop/bare-as-module3";
+import { baremuxPath } from "@mercuryworkshop/bare-mux/node";
+import { uvPath } from "@titaniumnetwork-dev/ultraviolet";
+import fastifyHelmet from '@fastify/helmet';
+import fastifyStatic from '@fastify/static';
+import pkg from "./routes.mjs";
+import { readFile } from 'node:fs/promises';
+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';
+const config = 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 rh = createRammerhead();
+const rammerheadScopes = [
+ "/rammerhead.js",
+ "/hammerhead.js",
+ "/transport-worker.js",
+ "/task.js",
+ "/iframe-task.js",
+ "/worker-hammerhead.js",
+ "/messaging",
+ "/sessionexists",
+ "/deletesession",
+ "/newsession",
+ "/editsession",
+ "/needpassword",
+ "/syncLocalStorage",
+ "/api/shuffleDict",
+ "/mainport",
+];
+const rammerheadSession = /^\/[a-z0-9]{32}/;
+const shouldRouteRh = req => {
+ const url = new URL(req.url, "http://0.0.0.0");
+ return (
+ rammerheadScopes.includes(url.pathname) ||
+ rammerheadSession.test(url.pathname)
+ );
+}
+const routeRhRequest = (req, res) => {
+ rh.emit("request", req, res);
+}
+const routeRhUpgrade = (req, socket, head) => {
+ rh.emit("upgrade", req, socket, head);
+}
+
+//create a server factory for RH, and wisp (and bare if you please)
+const serverFactory = (handler) => {
+ return createServer()
+ .on('request', (req, res) => {
+ if (shouldRouteRh(req)) {
+ routeRhRequest(req, res);
+ }
+ else {
+ handler(req, res);
+ }
+ })
+ .on('upgrade', (req, socket, head) => {
+ if (shouldRouteRh(req)) {
+ routeRhUpgrade(req, socket, head);
+ }
+ else if (req.url.endsWith('/wisp/')) {
+ wisp.routeRequest(req, socket, head);
+ }
+ })
+}
+
+//set logger to true for logs
+const app = Fastify({ logger: false, serverFactory: serverFactory });
+app.register(fastifyStatic, {
+ root: fileURLToPath(new URL('../views', import.meta.url)),
+});
+app.register(fastifyStatic, {
+ root: uvPath,
+ //due to how Fastify works, we have to have the uvPath live on a different prefix then the one in /views/
+ prefix: "/uv-static/",
+ decorateReply: false
+});
+app.register(fastifyStatic, {
+ root: epoxyPath,
+ prefix: "/epoxy/",
+ decorateReply: false
+});
+app.register(fastifyStatic, {
+ root: libcurlPath,
+ prefix: "/libcurl/",
+ decorateReply: false
+});
+app.register(fastifyStatic, {
+ root: bareModulePath,
+ prefix: "/bareasmodule/",
+ decorateReply: false
+});
+app.register(fastifyStatic, {
+ root: baremuxPath,
+ prefix: "/baremux/",
+ decorateReply: false
+});
+app.get("/", function(req, reply) {
+ reply.type('html');
+ reply.send(paintSource(loadTemplates(tryReadFile(path.join(__dirname, "views", "/?".indexOf(req.url) ? pages[Object.keys(req.query)[0]] || "error.html" : pages.index)))))
+});
+
+//host is set as to avoid just being on localhost
+app.listen({ port: port, host: '0.0.0.0' });
diff --git a/views/pages/frame.html b/views/pages/frame.html
index 2d74b482..0cb7fd5f 100644
--- a/views/pages/frame.html
+++ b/views/pages/frame.html
@@ -26,7 +26,7 @@
-
+
diff --git a/views/pages/nav/games5.html b/views/pages/nav/games5.html
index 6231b30c..1d15a37f 100644
--- a/views/pages/nav/games5.html
+++ b/views/pages/nav/games5.html
@@ -26,7 +26,7 @@
-
+
-
+
-
+
diff --git a/views/pages/proxnav/ultraviolet.html b/views/pages/proxnav/ultraviolet.html
index 62f679d6..7fe42d89 100644
--- a/views/pages/proxnav/ultraviolet.html
+++ b/views/pages/proxnav/ultraviolet.html
@@ -26,7 +26,7 @@
-
+