diff --git a/moderation/backend-py/main.py b/moderation/backend-py/main.py index c912547..9fb8de6 100644 --- a/moderation/backend-py/main.py +++ b/moderation/backend-py/main.py @@ -109,22 +109,25 @@ class SocketIOWrapper: path = scope.get("path", "") scope_type = scope.get("type", "") - # Логируем для отладки - print(f"[SocketIOWrapper] Request: type={scope_type}, path={path}, method={scope.get('method', 'N/A')}") + # Логируем для отладки (только для WebSocket и /socket.io) + if scope_type == "websocket" or path.startswith("/socket.io"): + print(f"[SocketIOWrapper] Request: type={scope_type}, path={path}, method={scope.get('method', 'N/A')}") # Если это WebSocket или путь начинается с /socket.io, используем Socket.IO if scope_type == "websocket" or path.startswith("/socket.io"): print(f"[SocketIOWrapper] ✅ Routing to Socket.IO: type={scope_type}, path={path}") try: + # Socket.IO ASGI app должен обработать WebSocket upgrade await self.socketio_app(scope, receive, send) except Exception as e: - print(f"[SocketIOWrapper] ❌ Error in Socket.IO: {e}") + print(f"[SocketIOWrapper] ❌ Error in Socket.IO: {type(e).__name__}: {e}") import traceback traceback.print_exc() - raise + # Для WebSocket ошибок не поднимаем исключение, чтобы не ломать соединение + if scope_type != "websocket": + raise else: # Иначе используем FastAPI - print(f"[SocketIOWrapper] → Routing to FastAPI: type={scope_type}, path={path}") await self.fastapi_app(scope, receive, send) # Создаем обернутое приложение (доступно для uvicorn) diff --git a/moderation/backend-py/websocket_server.py b/moderation/backend-py/websocket_server.py index 315d737..01fcb72 100644 --- a/moderation/backend-py/websocket_server.py +++ b/moderation/backend-py/websocket_server.py @@ -40,7 +40,10 @@ def broadcast_online(): @sio.on('connect', namespace='/mod-chat') async def on_connect(sid, environ): """Handle client connection to /mod-chat namespace""" + print(f"[WebSocket] ✅ Client connected to /mod-chat: {sid}") logger.info(f"[WebSocket] Client connected to /mod-chat: {sid}") + if environ: + print(f"[WebSocket] Environ keys: {list(environ.keys()) if isinstance(environ, dict) else 'N/A'}") # Don't authorize immediately - wait for 'auth' event @@ -136,5 +139,8 @@ async def on_message(sid, data): def get_socketio_app(): """Get Socket.IO ASGI app""" - return socketio.ASGIApp(sio) + # Socket.IO ASGI app должен обернуть FastAPI app для правильной работы + # Но мы делаем это в main.py через SocketIOWrapper + # Здесь просто возвращаем ASGI app для Socket.IO + return socketio.ASGIApp(sio, socketio_path='/socket.io') diff --git a/moderation/frontend/src/App.jsx b/moderation/frontend/src/App.jsx index 9679c6c..1416b10 100644 --- a/moderation/frontend/src/App.jsx +++ b/moderation/frontend/src/App.jsx @@ -719,7 +719,15 @@ export default function App() { }); socket.on('connect_error', (error) => { - console.error('Ошибка подключения WebSocket:', error); + console.error('[Chat] ❌ Ошибка подключения WebSocket:', error); + console.error('[Chat] Error details:', { + message: error.message, + type: error.type, + description: error.description, + context: error.context, + transport: error.transport + }); + setChatState((prev) => ({ ...prev, connected: false })); }); chatSocketRef.current = socket; diff --git a/nginx-moderation-production.conf b/nginx-moderation-production.conf index b8b7aca..ee244d4 100644 --- a/nginx-moderation-production.conf +++ b/nginx-moderation-production.conf @@ -87,12 +87,16 @@ server { } # WebSocket для Socket.IO (чат модераторов) - location /socket.io/ { + # ВАЖНО: location должен быть без trailing slash для Socket.IO + location /socket.io { proxy_pass http://127.0.0.1:3001; proxy_http_version 1.1; + # WebSocket upgrade headers proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; + + # Standard proxy headers proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -104,7 +108,9 @@ server { proxy_send_timeout 7d; proxy_read_timeout 7d; + # Отключить буферизацию для real-time proxy_buffering off; + proxy_request_buffering off; } # Статические файлы фронтенда