diff --git a/packages/hydrooj/src/handler/connection.ts b/packages/hydrooj/src/handler/connection.ts index 6dc333dce..f9e01b6f1 100644 --- a/packages/hydrooj/src/handler/connection.ts +++ b/packages/hydrooj/src/handler/connection.ts @@ -45,12 +45,6 @@ class WebsocketEventsConnectionManagerHandler extends ConnectionHandler { } async message(payload: any) { - try { - payload = JSON.parse(payload); - } catch (e) { - console.error('Invalid payload', e); - return; - } const success = []; const failed = []; const session = payload?.credential diff --git a/packages/ui-default/components/message/index.page.ts b/packages/ui-default/components/message/index.page.ts index 2c45b18a9..04c580b69 100644 --- a/packages/ui-default/components/message/index.page.ts +++ b/packages/ui-default/components/message/index.page.ts @@ -59,14 +59,14 @@ const onmessage = (msg) => { return true; }; -const initWorkerMode = (endpoint) => { +const initWorkerMode = () => { console.log('Messages: using SharedWorker'); const worker = new SharedWorker(new URL('./worker.ts', import.meta.url), { name: 'HydroMessagesWorker' }); worker.port.start(); window.addEventListener('beforeunload', () => { worker.port.postMessage({ type: 'unload' }); }); - worker.port.postMessage({ type: 'conn', path: endpoint, cookie: document.cookie }); + worker.port.postMessage({ type: 'conn', cookie: document.cookie }); worker.port.onmessage = async (message) => { if (process.env.NODE_ENV !== 'production') console.log('onmessage: ', message); const { payload, type } = message.data; @@ -89,13 +89,11 @@ const messagePage = new AutoloadPage('messagePage', (pagename) => { action: () => window.open('/home/messages', '_blank'), }).show(); } - const url = new URL(`${UiContext.ws_prefix}home/messages-conn`, window.location.href); - // TODO handle a better way for cookie - if (url.host !== window.location.host) url.searchParams.append('sid', document.cookie.split('sid=')[1].split(';')[0]); + const url = new URL(`${UiContext.ws_prefix}websocket`, window.location.href); const endpoint = url.toString().replace('http', 'ws'); if (window.SharedWorker) { try { - initWorkerMode(endpoint); + initWorkerMode(); return; } catch (e) { console.error('SharedWorker init fail: ', e.message); @@ -129,6 +127,14 @@ const messagePage = new AutoloadPage('messagePage', (pagename) => { localStorage.setItem('page.master', selfId); const masterChannel = new BroadcastChannel('hydro-messages'); const sock = new Sock(endpoint); + sock.onopen = () => { + sock.send(JSON.stringify({ + operation: 'subscribe', + request_id: Math.random().toString(16).substring(2), + credential: document.cookie.split('sid=')[1].split(';')[0], + channels: ['message'], + })); + }; sock.onmessage = async (message) => { const payload = JSON.parse(message.data); masterChannel.postMessage({ type: 'message', payload }); diff --git a/packages/ui-default/components/message/worker.ts b/packages/ui-default/components/message/worker.ts index c553133a9..24b6377f7 100644 --- a/packages/ui-default/components/message/worker.ts +++ b/packages/ui-default/components/message/worker.ts @@ -13,7 +13,6 @@ const ports: Set = new Set(); interface RequestInitSharedConnPayload { type: 'conn'; cookie: string; - path: string; } interface RequestAckPayload { type: 'ack'; @@ -53,19 +52,22 @@ function onMessage(payload: any) { }, 5000); } -function initConn(path: string, port: MessagePort, cookie: any) { +function initConn(port: MessagePort, cookie: any) { ports.add(port); - if (cookie !== lcookie) conn?.close(); - else if (conn && conn.readyState === conn.OPEN) return; - const url = new URL(path, location.origin); - if (cookie) url.searchParams.set('sid', cookie.split('sid=')[1].split(';')[0]); - lcookie = cookie; - console.log('Init connection for', path); - conn?.close(); - conn = new ReconnectingWebsocket(url.toString()); + console.log('Init connection'); + lcookie = cookie.split('sid=')[1].split(';')[0]; + if (conn) return; + const url = new URL('/websocket', location.origin); + conn = new ReconnectingWebsocket(url.toString().replace('http', 'ws')); conn.onopen = () => { - console.log('Connected to', path); + console.log('Connected'); broadcastMsg({ type: 'open' }); + conn.send(JSON.stringify({ + 'operation': 'subscribe', + 'request_id': Math.random().toString(16).substring(2), + 'credential': lcookie, + 'channels': ['message'], + })); }; conn.onerror = () => broadcastMsg({ type: 'error' }); conn.onclose = (ev) => broadcastMsg({ type: 'close', error: ev.reason }); @@ -79,8 +81,8 @@ function initConn(path: string, port: MessagePort, cookie: any) { if (['PermissionError', 'PrivilegeError'].includes(payload.error)) { broadcastMsg({ type: 'close', error: payload.error }); conn.close(); - } else { - onMessage(payload); + } else if (payload.operation === 'event') { + onMessage(payload.payload); } }; } @@ -89,7 +91,7 @@ self.onconnect = function (e) { const port = e.ports[0]; port.addEventListener('message', (msg: { data: RequestPayload }) => { - if (msg.data.type === 'conn') initConn(msg.data.path, port, msg.data.cookie); + if (msg.data.type === 'conn') initConn(port, msg.data.cookie); if (msg.data.type === 'ack') ack[msg.data.id]?.(); if (msg.data.type === 'unload') ports.delete(port); });