First Release of Claw3D (#11)
Co-authored-by: iamlukethedev <iamlukethedev@users.noreply.github.com>
This commit is contained in:
+130
@@ -0,0 +1,130 @@
|
||||
const http = require("node:http");
|
||||
const next = require("next");
|
||||
|
||||
const { createAccessGate } = require("./access-gate");
|
||||
const { createGatewayProxy } = require("./gateway-proxy");
|
||||
const { assertPublicHostAllowed, resolveHosts } = require("./network-policy");
|
||||
const { loadUpstreamGatewaySettings } = require("./studio-settings");
|
||||
|
||||
const resolvePort = () => {
|
||||
const raw = process.env.PORT?.trim() || "3000";
|
||||
const port = Number(raw);
|
||||
if (!Number.isFinite(port) || port <= 0) return 3000;
|
||||
return port;
|
||||
};
|
||||
|
||||
const resolvePathname = (url) => {
|
||||
const raw = typeof url === "string" ? url : "";
|
||||
const idx = raw.indexOf("?");
|
||||
return (idx === -1 ? raw : raw.slice(0, idx)) || "/";
|
||||
};
|
||||
|
||||
async function main() {
|
||||
const dev = process.argv.includes("--dev");
|
||||
const hostnames = Array.from(new Set(resolveHosts(process.env)));
|
||||
const hostname = hostnames[0] ?? "127.0.0.1";
|
||||
const port = resolvePort();
|
||||
for (const host of hostnames) {
|
||||
assertPublicHostAllowed({
|
||||
host,
|
||||
studioAccessToken: process.env.STUDIO_ACCESS_TOKEN,
|
||||
});
|
||||
}
|
||||
|
||||
const app = next({
|
||||
dev,
|
||||
hostname,
|
||||
port,
|
||||
...(dev ? { webpack: true } : null),
|
||||
});
|
||||
const handle = app.getRequestHandler();
|
||||
|
||||
const accessGate = createAccessGate({
|
||||
token: process.env.STUDIO_ACCESS_TOKEN,
|
||||
});
|
||||
|
||||
const proxy = createGatewayProxy({
|
||||
loadUpstreamSettings: async () => {
|
||||
const settings = loadUpstreamGatewaySettings(process.env);
|
||||
return { url: settings.url, token: settings.token };
|
||||
},
|
||||
allowWs: (req) => {
|
||||
if (resolvePathname(req.url) !== "/api/gateway/ws") return false;
|
||||
if (!accessGate.allowUpgrade(req)) return false;
|
||||
return true;
|
||||
},
|
||||
});
|
||||
|
||||
await app.prepare();
|
||||
const handleUpgrade = app.getUpgradeHandler();
|
||||
const handleServerUpgrade = (req, socket, head) => {
|
||||
if (resolvePathname(req.url) === "/api/gateway/ws") {
|
||||
proxy.handleUpgrade(req, socket, head);
|
||||
return;
|
||||
}
|
||||
handleUpgrade(req, socket, head);
|
||||
};
|
||||
|
||||
const createServer = () =>
|
||||
http.createServer((req, res) => {
|
||||
if (accessGate.handleHttp(req, res)) return;
|
||||
handle(req, res);
|
||||
});
|
||||
|
||||
const servers = hostnames.map(() => createServer());
|
||||
|
||||
const attachUpgradeHandlers = (server) => {
|
||||
server.on("upgrade", handleServerUpgrade);
|
||||
server.on("newListener", (eventName, listener) => {
|
||||
if (eventName !== "upgrade") return;
|
||||
if (listener === handleServerUpgrade) return;
|
||||
process.nextTick(() => {
|
||||
server.removeListener("upgrade", listener);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
for (const server of servers) {
|
||||
attachUpgradeHandlers(server);
|
||||
}
|
||||
|
||||
const listenOnHost = (server, host) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const onError = (err) => {
|
||||
server.off("error", onError);
|
||||
reject(err);
|
||||
};
|
||||
server.once("error", onError);
|
||||
server.listen(port, host, () => {
|
||||
server.off("error", onError);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
const closeServer = (server) =>
|
||||
new Promise((resolve) => {
|
||||
if (!server.listening) return resolve();
|
||||
server.close(() => resolve());
|
||||
});
|
||||
|
||||
try {
|
||||
await Promise.all(servers.map((server, index) => listenOnHost(server, hostnames[index])));
|
||||
} catch (err) {
|
||||
await Promise.all(servers.map((server) => closeServer(server)));
|
||||
throw err;
|
||||
}
|
||||
|
||||
const hostForBrowser = hostnames.some((value) => value === "127.0.0.1" || value === "::1")
|
||||
? "localhost"
|
||||
: hostname === "0.0.0.0" || hostname === "::"
|
||||
? "localhost"
|
||||
: hostname;
|
||||
|
||||
const browserUrl = `http://${hostForBrowser}:${port}`;
|
||||
console.info(`Open in browser: ${browserUrl}`);
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
Reference in New Issue
Block a user