Spaces:
Running
Running
Upload 126 files
Browse files
archives/neonstrike/app/server/index.js
CHANGED
|
@@ -197,7 +197,7 @@ const server = http.createServer((req, res) => {
|
|
| 197 |
|
| 198 |
// ---------------- websocket wiring ----------------
|
| 199 |
|
| 200 |
-
const wss = new WebSocketServer({ server, path: '/ws' });
|
| 201 |
|
| 202 |
wss.on('connection', (ws) => {
|
| 203 |
ws.isAlive = true;
|
|
|
|
| 197 |
|
| 198 |
// ---------------- websocket wiring ----------------
|
| 199 |
|
| 200 |
+
const wss = new WebSocketServer({ server, path: '/ws', perMessageDeflate: false });
|
| 201 |
|
| 202 |
wss.on('connection', (ws) => {
|
| 203 |
ws.isAlive = true;
|
archives/rblx/app/data/db.json
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
archives/rblx/app/server/realtime.js
CHANGED
|
@@ -343,12 +343,14 @@ function handleStudioMsg(ws, member, st, msg) {
|
|
| 343 |
// ---------------- wiring ----------------
|
| 344 |
|
| 345 |
function attach(server, apiRouter) {
|
| 346 |
-
const wss = new WebSocketServer({ server, path: '/ws' });
|
| 347 |
wss.on('error', () => {}); // http server owns error handling (port retry)
|
| 348 |
apiRouter.presence = () => presence;
|
| 349 |
|
| 350 |
wss.on('connection', (ws, req) => {
|
|
|
|
| 351 |
const user = userFromReq(req);
|
|
|
|
| 352 |
if (!user) {
|
| 353 |
send(ws, { t: 'error', error: 'Not logged in' });
|
| 354 |
ws.close();
|
|
|
|
| 343 |
// ---------------- wiring ----------------
|
| 344 |
|
| 345 |
function attach(server, apiRouter) {
|
| 346 |
+
const wss = new WebSocketServer({ server, path: '/ws', perMessageDeflate: false });
|
| 347 |
wss.on('error', () => {}); // http server owns error handling (port retry)
|
| 348 |
apiRouter.presence = () => presence;
|
| 349 |
|
| 350 |
wss.on('connection', (ws, req) => {
|
| 351 |
+
console.log('[RBLX-WS] Connection request, cookie:', req.headers.cookie);
|
| 352 |
const user = userFromReq(req);
|
| 353 |
+
console.log('[RBLX-WS] User resolved:', user ? user.username : 'null');
|
| 354 |
if (!user) {
|
| 355 |
send(ws, { t: 'error', error: 'Not logged in' });
|
| 356 |
ws.close();
|
server/index.js
CHANGED
|
@@ -102,32 +102,73 @@ function getRefererProxy(port) {
|
|
| 102 |
refererProxies[port] = createProxyMiddleware({
|
| 103 |
target: `http://localhost:${port}`,
|
| 104 |
changeOrigin: true,
|
| 105 |
-
ws: true,
|
| 106 |
logLevel: 'silent',
|
| 107 |
});
|
| 108 |
}
|
| 109 |
return refererProxies[port];
|
| 110 |
}
|
| 111 |
|
| 112 |
-
// 1. Redirect /play/:id to /play/:id/ to ensure proper relative asset resolution
|
| 113 |
app.use((req, res, next) => {
|
| 114 |
-
const match = req.path.match(/^\/play\/([^\/]+)
|
| 115 |
if (match) {
|
| 116 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
}
|
| 118 |
next();
|
| 119 |
});
|
| 120 |
|
| 121 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
app.use((req, res, next) => {
|
| 123 |
if (req.path === '/ws') return next();
|
| 124 |
if (req.path.startsWith('/api/entries') || req.path.startsWith('/archives') || req.path.startsWith('/play/')) {
|
| 125 |
return next();
|
| 126 |
}
|
| 127 |
-
const
|
| 128 |
-
|
| 129 |
-
if (match) {
|
| 130 |
-
const gameId = match[1];
|
| 131 |
const port = gamePorts[gameId];
|
| 132 |
if (port) {
|
| 133 |
const proxy = getRefererProxy(port);
|
|
@@ -138,13 +179,11 @@ app.use((req, res, next) => {
|
|
| 138 |
});
|
| 139 |
|
| 140 |
// 3. WS Proxy specifically for WebSocket connections to /ws
|
| 141 |
-
|
| 142 |
target: 'http://localhost:3000', // dummy fallback, overridden by router
|
| 143 |
router: (req) => {
|
| 144 |
-
const
|
| 145 |
-
|
| 146 |
-
if (match) {
|
| 147 |
-
const gameId = match[1];
|
| 148 |
const port = gamePorts[gameId];
|
| 149 |
if (port) {
|
| 150 |
return `http://localhost:${port}`;
|
|
@@ -155,7 +194,13 @@ app.use('/ws', createProxyMiddleware({
|
|
| 155 |
changeOrigin: true,
|
| 156 |
ws: true,
|
| 157 |
logLevel: 'silent',
|
| 158 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 159 |
|
| 160 |
app.use('/archives', express.static(ARCHIVES_DIR));
|
| 161 |
app.use(express.static(path.join(__dirname, '..', 'public')));
|
|
@@ -203,7 +248,6 @@ async function startGameServers() {
|
|
| 203 |
app.use(`/play/${entry.id}`, createProxyMiddleware({
|
| 204 |
target: `http://localhost:${port}`,
|
| 205 |
changeOrigin: true,
|
| 206 |
-
ws: true,
|
| 207 |
}));
|
| 208 |
|
| 209 |
console.log(`[proxy] /play/${entry.id} -> http://localhost:${port}`);
|
|
@@ -234,6 +278,7 @@ function cleanup() {
|
|
| 234 |
|
| 235 |
function listen(port) {
|
| 236 |
const srv = app.listen(port);
|
|
|
|
| 237 |
srv.on('error', (err) => {
|
| 238 |
if (err.code === 'EADDRINUSE') {
|
| 239 |
console.log(`port ${port} busy, trying ${port + 1}`);
|
|
|
|
| 102 |
refererProxies[port] = createProxyMiddleware({
|
| 103 |
target: `http://localhost:${port}`,
|
| 104 |
changeOrigin: true,
|
|
|
|
| 105 |
logLevel: 'silent',
|
| 106 |
});
|
| 107 |
}
|
| 108 |
return refererProxies[port];
|
| 109 |
}
|
| 110 |
|
| 111 |
+
// 1. Redirect /play/:id to /play/:id/ to ensure proper relative asset resolution and set active_game cookie
|
| 112 |
app.use((req, res, next) => {
|
| 113 |
+
const match = req.path.match(/^\/play\/([^\/]+)/);
|
| 114 |
if (match) {
|
| 115 |
+
const gameId = match[1];
|
| 116 |
+
const isSecure = req.secure || req.headers['x-forwarded-proto'] === 'https';
|
| 117 |
+
res.cookie('active_game', gameId, {
|
| 118 |
+
path: '/',
|
| 119 |
+
sameSite: isSecure ? 'none' : 'lax',
|
| 120 |
+
secure: isSecure
|
| 121 |
+
});
|
| 122 |
+
if (req.path === `/play/${gameId}`) {
|
| 123 |
+
return res.redirect(301, `${req.path}/`);
|
| 124 |
+
}
|
| 125 |
}
|
| 126 |
next();
|
| 127 |
});
|
| 128 |
|
| 129 |
+
// Helper to extract game ID from referer or cookies
|
| 130 |
+
function getGameId(req) {
|
| 131 |
+
const referer = req.headers.referer || '';
|
| 132 |
+
|
| 133 |
+
// 1. Try to extract game ID directly from Referer (e.g. /play/rblx/...)
|
| 134 |
+
const refMatch = referer.match(/\/play\/([^\/]+)/);
|
| 135 |
+
if (refMatch) {
|
| 136 |
+
return refMatch[1];
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
// 2. Determine if the referer is the main portal page (path is exactly "/")
|
| 140 |
+
let isPortal = false;
|
| 141 |
+
if (referer) {
|
| 142 |
+
try {
|
| 143 |
+
const refUrl = new URL(referer);
|
| 144 |
+
if (refUrl.pathname === '/') {
|
| 145 |
+
isPortal = true;
|
| 146 |
+
}
|
| 147 |
+
} catch (e) {
|
| 148 |
+
// Ignore URL parsing errors
|
| 149 |
+
}
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
// 3. Fallback to cookie if we are not on the portal page
|
| 153 |
+
if (!isPortal) {
|
| 154 |
+
const cookieHeader = req.headers.cookie || '';
|
| 155 |
+
const cookieMatch = cookieHeader.match(/(?:^|; )active_game=([^;]*)/);
|
| 156 |
+
if (cookieMatch) {
|
| 157 |
+
return cookieMatch[1];
|
| 158 |
+
}
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
return null;
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
// 2. Referer/Cookie-based HTTP proxy for absolute paths (e.g. /css/..., /js/..., /api/...)
|
| 165 |
app.use((req, res, next) => {
|
| 166 |
if (req.path === '/ws') return next();
|
| 167 |
if (req.path.startsWith('/api/entries') || req.path.startsWith('/archives') || req.path.startsWith('/play/')) {
|
| 168 |
return next();
|
| 169 |
}
|
| 170 |
+
const gameId = getGameId(req);
|
| 171 |
+
if (gameId) {
|
|
|
|
|
|
|
| 172 |
const port = gamePorts[gameId];
|
| 173 |
if (port) {
|
| 174 |
const proxy = getRefererProxy(port);
|
|
|
|
| 179 |
});
|
| 180 |
|
| 181 |
// 3. WS Proxy specifically for WebSocket connections to /ws
|
| 182 |
+
const wsProxy = createProxyMiddleware({
|
| 183 |
target: 'http://localhost:3000', // dummy fallback, overridden by router
|
| 184 |
router: (req) => {
|
| 185 |
+
const gameId = getGameId(req);
|
| 186 |
+
if (gameId) {
|
|
|
|
|
|
|
| 187 |
const port = gamePorts[gameId];
|
| 188 |
if (port) {
|
| 189 |
return `http://localhost:${port}`;
|
|
|
|
| 194 |
changeOrigin: true,
|
| 195 |
ws: true,
|
| 196 |
logLevel: 'silent',
|
| 197 |
+
on: {
|
| 198 |
+
error: (err, req, res) => {
|
| 199 |
+
console.error('[ws-proxy] error:', err);
|
| 200 |
+
}
|
| 201 |
+
}
|
| 202 |
+
});
|
| 203 |
+
app.use('/ws', wsProxy);
|
| 204 |
|
| 205 |
app.use('/archives', express.static(ARCHIVES_DIR));
|
| 206 |
app.use(express.static(path.join(__dirname, '..', 'public')));
|
|
|
|
| 248 |
app.use(`/play/${entry.id}`, createProxyMiddleware({
|
| 249 |
target: `http://localhost:${port}`,
|
| 250 |
changeOrigin: true,
|
|
|
|
| 251 |
}));
|
| 252 |
|
| 253 |
console.log(`[proxy] /play/${entry.id} -> http://localhost:${port}`);
|
|
|
|
| 278 |
|
| 279 |
function listen(port) {
|
| 280 |
const srv = app.listen(port);
|
| 281 |
+
srv.on('upgrade', wsProxy.upgrade);
|
| 282 |
srv.on('error', (err) => {
|
| 283 |
if (err.code === 'EADDRINUSE') {
|
| 284 |
console.log(`port ${port} busy, trying ${port + 1}`);
|