Update files

This commit is contained in:
glpshchn 2025-12-15 07:25:03 +03:00
parent c39c26b52b
commit 3074fc7566
2 changed files with 34 additions and 40 deletions

View File

@ -19,7 +19,9 @@ sio = socketio.AsyncServer(
logger=True, # Включить логирование для отладки logger=True, # Включить логирование для отладки
engineio_logger=True, # Включить логирование Engine.IO engineio_logger=True, # Включить логирование Engine.IO
ping_timeout=60, ping_timeout=60,
ping_interval=25 ping_interval=25,
allow_upgrades=True, # Разрешить upgrade с polling на websocket
transports=['polling', 'websocket'] # Поддерживаемые транспорты
) )
# Track connected moderators # Track connected moderators
@ -38,39 +40,26 @@ def broadcast_online():
sio.emit('online', online_list, namespace='/mod-chat') sio.emit('online', online_list, namespace='/mod-chat')
# Создаем класс для корневого namespace # Обработчик для корневого namespace (требуется для Socket.IO handshake)
class RootNamespace(socketio.AsyncNamespace): # В python-socketio для ASGI режима нужно использовать декоратор БЕЗ явного namespace='/'
"""Root namespace handler for Socket.IO handshake""" # или использовать namespace=None для корневого namespace
async def on_connect(self, sid, environ): @sio.on('connect')
"""Handle client connection to root namespace (Socket.IO handshake)""" async def on_connect_root(sid, environ):
print(f"[WebSocket] 🔄 Handshake to ROOT namespace: {sid}") """Handle client connection to root namespace (Socket.IO handshake)"""
print(f"[WebSocket] Environ type: {type(environ)}") print(f"[WebSocket] 🔄 Handshake to ROOT namespace: {sid}")
if environ: print(f"[WebSocket] Environ type: {type(environ)}")
print(f"[WebSocket] Environ keys: {list(environ.keys()) if isinstance(environ, dict) else 'N/A'}") if environ:
logger.info(f"[WebSocket] Handshake to ROOT namespace: {sid}") print(f"[WebSocket] Environ keys: {list(environ.keys()) if isinstance(environ, dict) else 'N/A'}")
# Разрешаем подключение для handshake logger.info(f"[WebSocket] Handshake to ROOT namespace: {sid}")
# В AsyncNamespace не нужно возвращать True явно, но можно
return True
async def on_disconnect(self, sid):
"""Handle disconnection from root namespace"""
print(f"[WebSocket] Client disconnected from ROOT namespace: {sid}")
logger.info(f"[WebSocket] Client disconnected from ROOT namespace: {sid}")
# Регистрируем корневой namespace ПЕРЕД созданием ASGI app
root_ns = RootNamespace('/')
sio.register_namespace(root_ns)
print(f"[WebSocket] ✅ Корневой namespace зарегистрирован: {root_ns.namespace}")
# Также добавляем обработчик через декоратор для надежности
@sio.on('connect', namespace='/')
async def on_connect_root_decorator(sid, environ):
"""Handle client connection to root namespace (Socket.IO handshake) - декоратор"""
print(f"[WebSocket] 🔄 Handshake to ROOT namespace (decorator): {sid}")
logger.info(f"[WebSocket] Handshake to ROOT namespace (decorator): {sid}")
# Разрешаем подключение для handshake # Разрешаем подключение для handshake
return True return True
@sio.on('disconnect')
async def on_disconnect_root(sid):
"""Handle disconnection from root namespace"""
print(f"[WebSocket] Client disconnected from ROOT namespace: {sid}")
logger.info(f"[WebSocket] Client disconnected from ROOT namespace: {sid}")
# Namespace handlers for /mod-chat # Namespace handlers for /mod-chat
@sio.on('connect', namespace='/mod-chat') @sio.on('connect', namespace='/mod-chat')
async def on_connect(sid, environ): async def on_connect(sid, environ):

View File

@ -653,22 +653,27 @@ export default function App() {
hasUsername: !!user.username, hasUsername: !!user.username,
hasTelegramId: !!user.telegramId hasTelegramId: !!user.telegramId
}); });
// Socket.IO подключается к /socket.io, но использует namespace /mod-chat // Способ 1: Подключение с явным указанием path и namespace
// В production Socket.IO слушает на /socket.io, namespace указывается отдельно const socketUrl = socketBase.endsWith('/socket.io')
const socketUrl = socketBase.endsWith('/socket.io') ? socketBase : `${socketBase}/socket.io`; ? socketBase.replace('/socket.io', '')
console.log('[Chat] Подключение к Socket.IO:', socketUrl); : socketBase;
console.log('[Chat] Подключение к Socket.IO base URL:', socketUrl);
console.log('[Chat] Использование namespace: /mod-chat'); console.log('[Chat] Использование namespace: /mod-chat');
// Подключаемся к корневому URL, но указываем namespace в опциях // Подключаемся к base URL с указанием path и namespace
const socket = io(socketUrl, { const socket = io(socketUrl, {
path: '/socket.io', path: '/socket.io',
namespace: '/mod-chat', namespace: '/mod-chat',
transports: ['websocket', 'polling'], transports: ['polling', 'websocket'], // Пробуем сначала polling, потом websocket
reconnection: true, reconnection: true,
reconnectionDelay: 1000, reconnectionDelay: 1000,
reconnectionAttempts: 5, reconnectionAttempts: 10,
timeout: 10000, timeout: 20000,
forceNew: false forceNew: true, // Принудительно новое соединение
autoConnect: true,
upgrade: true,
rememberUpgrade: false
}); });
socket.on('connect', () => { socket.on('connect', () => {