Pepguy's picture
Update app.js
2fe2d50 verified
raw
history blame
4.47 kB
// server.js (Bun) — with CORS enabled for WS and HTTP
const rooms = new Map(); // roomId ⇒ Set<ServerWebSocket>
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") {
// 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 });
}
// Serve HTML UI for non-WebSocket requests
if (url.pathname === "/") {
return new Response(`<!doctype html>
<html><head>
<title>Dubem Realtime Rooms</title>
<meta charset="utf-8"/>
<style>
body { font-family: sans-serif; padding: 20px; background: #f0f0f0; }
#log { border: 1px solid #ccc; height:200px; overflow-y:auto; padding:10px; background:#fff;}
input, button { margin:5px 0; padding:8px; font-size:16px; }
</style>
</head><body>
<h2>Join a Room & Send Messages</h2>
<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>
var ws, currentRoom;
window.addEventListener('load', function() {
var scheme = location.protocol === 'https:' ? 'wss' : 'ws';
var socketUrl = scheme + '://' + location.host + '/';
ws = new WebSocket(socketUrl);
ws.onopen = function(){ log('🔌 Connected'); };
ws.onmessage = function(ev){
var m = JSON.parse(ev.data);
log('[' + m.roomId + '] ' + m.message);
};
ws.onerror = function(){ log('⚠️ WebSocket error'); };
ws.onclose = function(c){ log('❌ Disconnected (code='+c.code+')'); };
});
function joinRoom(){
var 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(){
var 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){
var 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) {
// Leave all rooms
for (const set of rooms.values()) set.delete(ws);
// Join target room
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) { // OPEN
client.send(payload);
}
}
}
},
close(ws) {
// Clean up on disconnect
for (const set of rooms.values()) set.delete(ws);
}
}
});
console.log("✅ Bun realtime server running on port " + (Bun.env.PORT || 7860));