diff --git a/.gitignore b/.gitignore index 6292299..86f2a45 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ package-lock.json desktop.ini public/ +proxy_linux-x64 # Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore diff --git a/bun.lockb b/bun.lockb index f089f7d..6b39d09 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 38d411e..1e08e64 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,9 @@ "build": "NODE_ENV=production bun run ./build.ts", "build:dev": "NODE_ENV=development bun run ./build.ts", "format": "prettier --write --list-different .", - "format:check": "prettier --check ." + "format:check": "prettier --check .", + "proxy": "bun run ./proxy.ts", + "proxy:build": "bun build ./proxy.ts --compile --minify --target=bun-linux-x64-modern --outfile ./proxy_linux-x64" }, "dependencies": { "chalk": "^5.3.0", @@ -18,6 +20,7 @@ "cookie-parser": "^1.4.6", "express": "^4.21.0", "helmet": "^7.1.0", + "http-proxy": "^1.18.1", "indexeddb-export-import": "^2.1.5", "jquery": "^3.7.1", "morgan": "^1.10.0", @@ -35,6 +38,7 @@ "@types/eslint-config-prettier": "^6.11.3", "@types/eslint__js": "^8.42.3", "@types/html-minifier": "^4.0.5", + "@types/http-proxy": "^1.17.15", "@types/jquery": "^3.5.30", "@types/morgan": "^1.9.9", "@types/pako": "^2.0.3", diff --git a/proxy.ts b/proxy.ts new file mode 100644 index 0000000..8a862bf --- /dev/null +++ b/proxy.ts @@ -0,0 +1,23 @@ +import express from 'express'; +import morgan from 'morgan'; +import httpProxy from 'http-proxy'; + +const PORT = process.env['PORT'] ?? 3000; + +const proxy = httpProxy.createProxyServer({ + target: 'https://launcher.orionzleon.me', + ws: true, + xfwd: true, + secure: true, + changeOrigin: true, +}); + +const app = express(); + +app.use(morgan('combined')); + +app.use((req, res) => proxy.web(req, res)); + +app.listen(PORT, () => + console.log(`Server running on http://localhost:${PORT}/`), +); diff --git a/proxy/build.sh b/proxy/build.sh deleted file mode 100755 index 65e7e25..0000000 --- a/proxy/build.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash -echo 'Make sure you are running this in the `proxy` directory' && -rm -rf ./bin && -mkdir ./bin && -bun build ./proxy.ts --compile --minify --target=bun-linux-x64-modern --outfile ./bin/linux-x64 && -chmod +x ./bin/linux-x64 && -bun build ./proxy.ts --compile --minify --target=bun-linux-x64-baseline --outfile ./bin/linux-x64-compatibility && -chmod +x ./bin/linux-x64-compatibility && -bun build ./proxy.ts --compile --minify --target=bun-linux-arm64-modern --outfile ./bin/linux-arm64 && -chmod +x ./bin/linux-arm64 && -bun build ./proxy.ts --compile --minify --target=bun-linux-arm64-baseline --outfile ./bin/linux-arm64-compatibility && -chmod +x ./bin/linux-arm64-compatibility diff --git a/proxy/proxy.ts b/proxy/proxy.ts deleted file mode 100644 index a3a74af..0000000 --- a/proxy/proxy.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { type IncomingHttpHeaders } from 'http'; -import https from 'https'; -import express from 'express'; -import morgan from 'morgan'; - -if (Number(process.env['CACHE_MINUTES'] ?? 10) < 5) - process.env['CACHE_MINUTES'] = '5'; - -const PORT = process.env['PORT'] ?? 3000; -const CACHE_MINUTES = process.env['CACHE_MINUTES'] ?? 10; -const CACHE_SIZE = process.env['CACHE_SIZE'] ?? 0.5; - -const cache = new Map< - string, - { - lastFetched: number; - statusCode: number; - headers: IncomingHttpHeaders; - data: Buffer; - } ->(); -const maxCacheSize = 1024 * 1024 * 1024 * Number(CACHE_SIZE); -let cacheSize = 0; -const cacheLifetime = 1000 * 60 * Number(CACHE_MINUTES); -const proxyHostname = 'launcher.orionzleon.me'; -const requestCounter = new Map(); - -const app = express(); - -app.use(morgan(':method :url :status - :response-time ms')); - -app.use((req, res) => { - if (req.method === 'GET' && cache.has(req.url)) { - const cached = cache.get(req.url); - if (cached && Date.now() - cached.lastFetched < cacheLifetime) { - requestCounter.set(req.url, (requestCounter.get(req.url) ?? 0) + 1); - res.writeHead(cached.statusCode, cached.headers).end(cached.data); - } - } else { - const proxyReq = https.request( - { - hostname: proxyHostname, - path: req.url, - method: req.method, - }, - (proxyRes) => { - const statusCode = proxyRes.statusCode ?? 500; - const headers = proxyRes.headers; - - const responseChunks: Buffer[] = []; - - proxyRes.on('data', (chunk) => responseChunks.push(chunk)); - - proxyRes.on('end', () => { - const responseData = Buffer.concat(responseChunks); - - if (req.method === 'GET') { - cache.set(req.url, { - lastFetched: Date.now(), - statusCode: statusCode, - headers: headers, - data: responseData, - }); - - requestCounter.set(req.url, (requestCounter.get(req.url) ?? 0) + 1); - - cacheSize += responseData.length; - if (cacheSize > maxCacheSize) { - const keys = Array.from(cache.keys()); - keys.sort( - (a, b) => - (requestCounter.get(a) ?? 0) - (requestCounter.get(b) ?? 0), - ); - while (cacheSize > maxCacheSize && keys.length > 0) { - const key = keys.shift(); - if (key) { - const cached = cache.get(key); - if (cached) { - cacheSize -= cached.data.length; - cache.delete(key); - } - } - } - } - } - - res.writeHead(statusCode, headers).end(responseData); - }); - }, - ); - - proxyReq.on('error', () => { - if (req.method === 'GET' && cache.has(req.url)) { - const cached = cache.get(req.url); - if (cached) { - requestCounter.set(req.url, (requestCounter.get(req.url) ?? 0) + 1); - res.writeHead(cached.statusCode, cached.headers).end(cached.data); - } - } else - res - .writeHead(500, { 'Content-Type': 'text/plain' }) - .end('500 Internal Server Error'); - }); - - proxyReq.end(); - } -}); - -app.listen(PORT, () => - console.log( - `Server running on http://localhost:${PORT}/\n\nConfiguration:\n Maximum memory usage: ${CACHE_SIZE} GiB\n Cache TTL: ${CACHE_MINUTES} minutes`, - ), -);