feat: enhance WebSocket proxy with user connection management and status reporting

- Updated StudioOpts type to include infoList for user connection status.
- Added rendering of connection info in createStudioAppListHtml.
- Modified self-restart logic to use a specific app path.
- Improved WebSocket connection handling in wsProxyManager, including user registration and ID management.
- Implemented connection status checks and responses in UserV1Proxy.
- Introduced renderServerHtml function to inject server data into HTML responses.
- Refactored page-proxy request handling for better URL management.
This commit is contained in:
2026-03-05 03:58:46 +08:00
parent aaedcb881b
commit bbdf9f087d
9 changed files with 451 additions and 270 deletions

View File

@@ -3,46 +3,40 @@ import { getLoginUserByToken } from '@/modules/auth.ts';
import { logger } from '../logger.ts';
export const wsProxyManager = new WsProxyManager();
import { WebSocketListenerFun } from '@kevisual/router/src/server/server-type.ts'
// 生成一个随机六位字符串作为注册 ID
const generateRegistryId = () => {
return Math.random().toString(36).substring(2, 8);
}
export const wssFun: WebSocketListenerFun = async (req, res) => {
// do nothing, just to enable ws upgrade event
const { id, ws, token, data, emitter } = req;
// console.log('req', req)
const { type } = data || {};
if (type === 'registryClient') {
const loginUser = await getLoginUserByToken(token);
if (!loginUser?.tokenUser) {
logger.debug('未登录,断开连接');
ws.send(JSON.stringify({ code: 401, message: '未登录' }));
setTimeout(() => {
ws.close(401, 'Unauthorized');
}, 1000);
let isLogin = false;
let user = '';
if (loginUser?.tokenUser) {
isLogin = true;
user = loginUser?.tokenUser?.username;
} else {
logger.debug('未登录,请求等待用户验证', data);
user = data?.username || '';
}
if (!user) {
logger.debug('未提供用户名,无法注册 ws 连接');
ws.close();
return;
}
const user = loginUser?.tokenUser?.username;
const userApp = user + '--' + id;
logger.debug('注册 ws 连接', userApp);
const wsMessage = wsProxyManager.get(userApp);
if (wsMessage) {
logger.debug('ws 连接已存在,关闭旧连接', userApp);
wsMessage.ws.close();
wsProxyManager.unregister(userApp);
await new Promise((resolve) => setTimeout(resolve, 200));
let userApp = user + '--' + id;
// TODO: 如果存在, 而且之前的那个关闭了,不需要验证,直接覆盖和复用.
let wsConnect = await wsProxyManager.createNewConnection({ ws, user, userApp, isLogin });
if (wsConnect.isNew) {
logger.debug('新连接注册成功', userApp);
}
// @ts-ignore
wsProxyManager.register(userApp, { user, ws });
ws.send(
JSON.stringify({
type: 'connected',
user: user,
id,
}),
);
emitter.once('close--' + id, () => {
logger.debug('ws emitter closed');
wsProxyManager.unregister(userApp);
});
// @ts-ignore
ws.data.userApp = userApp;
ws.data.userApp = wsConnect.id;
return;
}
// @ts-ignore