Spaces:
Running
Running
File size: 4,690 Bytes
072db80 67d31ad 072db80 7fe989f 67d31ad 7fe989f 67d31ad d3bdf51 b977bfa 072db80 b977bfa 67d31ad be81bd0 072db80 b977bfa be81bd0 072db80 be81bd0 072db80 be81bd0 7c9ff5c 072db80 7fe989f 072db80 7fe989f 072db80 7c9ff5c 072db80 2fe2d50 072db80 be81bd0 072db80 be81bd0 072db80 7fe989f be81bd0 072db80 be81bd0 7fe989f be81bd0 072db80 b977bfa be81bd0 b977bfa be81bd0 904caf7 d3bdf51 b977bfa d3bdf51 67d31ad 072db80 67d31ad 072db80 67d31ad 7fe989f 6d4d78a 072db80 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
// server.js (Bun)
const rooms = new Map(); // roomId ⇒ Set<ServerWebSocket>
const VALID_TOKEN = "mysecrettoken"; // ← your hard-coded secret
Bun.serve({
port: Number(Bun.env.PORT) || 7860,
fetch(req, server) {
const url = new URL(req.url);
// Handle CORS preflight
if (req.method === "OPTIONS") {
return new Response(null, { status: 204, headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Upgrade",
"Access-Control-Allow-Credentials": "true",
}});
}
// Upgrade to WebSocket if requested
if (req.headers.get("upgrade")?.toLowerCase() === "websocket") {
// **AUTH CHECK**: require ?token=VALID_TOKEN
const clientToken = url.searchParams.get("token");
if (clientToken !== VALID_TOKEN) {
return new Response("Unauthorized", { status: 401 });
}
// Accept the upgrade with CORS headers on the handshake
const upgradeRes = server.upgrade(req, {
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": "true",
},
});
return upgradeRes ?? new Response("Upgrade failed", { status: 500 });
}
// … your existing HTML serve code unchanged …
if (url.pathname === "/") {
return new Response(`<!doctype html>
<html><head><title>Dubem Realtime Rooms</title><meta charset="utf-8"/></head><body>
<h2>Join a Room & Send Messages</h2>
<label><input type="checkbox" id="authToggle" checked> Send Auth Token?</label><br/>
<input id="room" placeholder="Room ID"/><button onclick="joinRoom()">Join Room</button>
<div id="log"></div>
<input id="msg" placeholder="Type a message" style="width:80%;"/><button onclick="sendMsg()">Send</button>
<script>
const VALID_TOKEN = "mysecrettoken"; // must match backend
let includeAuth = true; //false;
document.getElementById("authToggle").addEventListener("change", e => {
includeAuth = e.target.checked;
connect(); // reconnect on toggle
});
let ws, currentRoom;
function connect() {
if (ws) ws.close();
const scheme = location.protocol === 'https:' ? 'wss' : 'ws';
let socketUrl = scheme + '://' + location.host + '/';
if (includeAuth) socketUrl += "?token=" + VALID_TOKEN;
ws = new WebSocket(socketUrl);
ws.onopen = () => log('🔌 Connected');
ws.onmessage = ev => { const m = JSON.parse(ev.data); log('['+m.roomId+'] '+m.message); };
ws.onerror = () => log('⚠️ WebSocket error');
ws.onclose = c => log('❌ Disconnected (code='+c.code+')');
}
window.addEventListener('load', connect);
function joinRoom(){
const id = document.getElementById('room').value.trim();
if(!id) return alert('Enter room ID');
ws.send(JSON.stringify({ action:'join', roomId:id }));
currentRoom = id;
log('➡️ Joined '+id);
}
function sendMsg(){
const t = document.getElementById('msg').value.trim();
if(!t) return;
if(!currentRoom) return alert('Join a room first');
ws.send(JSON.stringify({ action:'post', roomId:currentRoom, message:t }));
document.getElementById('msg').value = '';
}
function log(txt){
const e = document.getElementById('log');
e.innerHTML += '<div>'+txt+'</div>';
e.scrollTop = e.scrollHeight;
}
</script>
</body></html>`, {
headers: {
"Content-Type": "text/html; charset=utf-8",
"Access-Control-Allow-Origin": "*",
}
});
}
return new Response("Not Found", {
status: 404,
headers: { "Access-Control-Allow-Origin": "*" },
});
},
websocket: {
message(ws, raw) {
let msg;
try { msg = JSON.parse(raw); } catch { return; }
if (msg.action === "join" && msg.roomId) {
for (const set of rooms.values()) set.delete(ws);
let set = rooms.get(msg.roomId);
if (!set) { set = new Set(); rooms.set(msg.roomId, set); }
set.add(ws);
}
if (msg.action === "post" && msg.roomId && msg.message) {
const set = rooms.get(msg.roomId);
if (!set) return;
const payload = JSON.stringify({
roomId: msg.roomId,
message: msg.message,
timestamp: Date.now(),
});
for (const client of set) {
if (client.readyState === 1) client.send(payload);
}
}
},
close(ws) {
for (const set of rooms.values()) set.delete(ws);
}
}
});
console.log("✅ Bun realtime server running on port " + (Bun.env.PORT || 7860)); |