diff --git a/server/bc.js b/server/bc.js index 36b90a7..725586c 100644 --- a/server/bc.js +++ b/server/bc.js @@ -18,31 +18,35 @@ const app = express(); const server = http.createServer(app); // --- НАСТРОЙКА EXPRESS --- -const clientOrigin = process.env.CORS_ORIGIN_CLIENT || (process.env.NODE_ENV === 'development' ? '*' : undefined); -console.log(`[BC Server] NODE_ENV: ${process.env.NODE_ENV}`); -console.log(`[BC Server] process.env.CORS_ORIGIN_CLIENT: ${process.env.CORS_ORIGIN_CLIENT}`); -console.log(`[BC Server] Calculated HTTP CORS Origin (clientOrigin): ${clientOrigin === '*' ? "'*'" : clientOrigin || 'Not explicitly set (will likely fail if not development)'}`); +console.log(`[BC.JS CONFIG] Reading environment variables...`); +console.log(`[BC.JS CONFIG] NODE_ENV: ${process.env.NODE_ENV}`); +console.log(`[BC.JS CONFIG] process.env.CORS_ORIGIN_CLIENT: ${process.env.CORS_ORIGIN_CLIENT}`); -if (!clientOrigin && process.env.NODE_ENV !== 'development') { - console.warn("[BC Server Config] CORS_ORIGIN_CLIENT не установлен для не-development сборки. HTTP API могут быть недоступны."); +const clientOrigin = process.env.CORS_ORIGIN_CLIENT || (process.env.NODE_ENV === 'development' ? '*' : undefined); +// Этот лог покажет, какое значение clientOrigin будет использовано для HTTP CORS +console.log(`[BC.JS CONFIG] Effective clientOrigin for HTTP CORS: ${clientOrigin === '*' ? "'*'" : clientOrigin || 'NOT SET (CORS will likely fail if not development)'}`); + +if (!clientOrigin && process.env.NODE_ENV !== 'development' && process.env.NODE_ENV !== undefined) { // Добавил проверку на undefined NODE_ENV + console.warn("[BC.JS CONFIG WARNING] CORS_ORIGIN_CLIENT is not set for a non-development and non-undefined NODE_ENV. HTTP API requests from browsers might be blocked by CORS."); } app.use(cors({ origin: clientOrigin, methods: ["GET", "POST"], - credentials: true + credentials: true // Важно, если клиент шлет куки или заголовок Authorization })); app.use(express.json()); const publicPath = path.join(__dirname, '..', 'public'); -console.log(`[BC Server] Serving static files from: ${publicPath}`); +console.log(`[BC.JS CONFIG] Serving static files from: ${publicPath}`); app.use(express.static(publicPath)); // --- HTTP МАРШРУТЫ АУТЕНТИФИКАЦИИ --- app.post('/auth/register', async (req, res) => { const { username, password } = req.body; - console.log(`[BC HTTP /auth/register] Attempt for username: "${username}" from IP: ${req.ip}`); + // Логируем входящий Origin для этого запроса + console.log(`[BC HTTP /auth/register] Attempt for username: "${username}" from IP: ${req.ip}. Origin header: ${req.headers.origin}`); if (!username || !password) { console.warn('[BC HTTP /auth/register] Bad request: Username or password missing.'); return res.status(400).json({ success: false, message: 'Имя пользователя и пароль обязательны.' }); @@ -59,6 +63,7 @@ app.post('/auth/register', async (req, res) => { app.post('/auth/login', async (req, res) => { const { username, password } = req.body; + // Логируем входящий Origin для этого запроса console.log(`[BC HTTP /auth/login] Attempt for username: "${username}" from IP: ${req.ip}. Origin header: ${req.headers.origin}`); if (!username || !password) { console.warn('[BC HTTP /auth/login] Bad request: Username or password missing.'); @@ -75,28 +80,24 @@ app.post('/auth/login', async (req, res) => { }); // --- НАСТРОЙКА SOCKET.IO --- +console.log(`[BC.JS CONFIG] process.env.CORS_ORIGIN_SOCKET: ${process.env.CORS_ORIGIN_SOCKET}`); const socketCorsOrigin = process.env.CORS_ORIGIN_SOCKET || (process.env.NODE_ENV === 'development' ? '*' : undefined); -console.log(`[BC Server] process.env.CORS_ORIGIN_SOCKET: ${process.env.CORS_ORIGIN_SOCKET}`); -console.log(`[BC Server] Calculated Socket.IO CORS Origin (socketCorsOrigin): ${socketCorsOrigin === '*' ? "'*'" : socketCorsOrigin || 'Not explicitly set (will likely fail if not development)'}`); +// Этот лог покажет, какое значение socketCorsOrigin будет использовано для Socket.IO CORS +console.log(`[BC.JS CONFIG] Effective socketCorsOrigin for Socket.IO CORS: ${socketCorsOrigin === '*' ? "'*'" : socketCorsOrigin || 'NOT SET (Socket.IO CORS will likely fail if not development)'}`); -if (!socketCorsOrigin && process.env.NODE_ENV !== 'development') { - console.warn("[BC Server Config] CORS_ORIGIN_SOCKET не установлен для не-development сборки. Socket.IO может быть недоступен."); +if (!socketCorsOrigin && process.env.NODE_ENV !== 'development' && process.env.NODE_ENV !== undefined) { // Добавил проверку на undefined NODE_ENV + console.warn("[BC.JS CONFIG WARNING] CORS_ORIGIN_SOCKET is not set for a non-development and non-undefined NODE_ENV. Socket.IO connections from browsers might be blocked by CORS."); } const io = new Server(server, { - // ВАЖНО: Этот path должен соответствовать тому, как клиент подключается - // и как прокси настроен (особенно stripPrefix для /socket.io). - // Если клиент и прокси работают с /socket.io/ и прокси НЕ отрезает этот префикс - // (stripPrefix: false для /socket.io в config.json), то здесь ДОЛЖЕН быть path. - path: '/socket.io/', // <--- УБЕДИТЕСЬ, ЧТО ЭТА СТРОКА РАСКОММЕНТИРОВАНА И КОРРЕКТНА + path: '/socket.io/', // Убедитесь, что это соответствует настройкам клиента и прокси cors: { origin: socketCorsOrigin, methods: ["GET", "POST"], credentials: true }, - // transports: ['websocket', 'polling'], // Можно оставить по умолчанию или указать явно }); -console.log(`[BC Server] Socket.IO server configured with path: ${io.path()} and CORS origin: ${socketCorsOrigin === '*' ? "'*'" : socketCorsOrigin || 'Not set'}`); +console.log(`[BC.JS CONFIG] Socket.IO server configured with path: ${io.path()} and effective CORS origin: ${io.opts.cors.origin === '*' ? "'*'" : io.opts.cors.origin || 'NOT SET'}`); const gameManager = new GameManager(io); @@ -105,8 +106,12 @@ const loggedInUsers = {}; // --- MIDDLEWARE АУТЕНТИФИКАЦИИ SOCKET.IO --- io.use(async (socket, next) => { const token = socket.handshake.auth.token; - const clientIp = socket.handshake.address; // Может быть IP прокси, если xfwd не настроен на уровне Socket.IO - console.log(`[BC Socket.IO Middleware] Auth attempt for socket ${socket.id} from IP ${clientIp}. Token ${token ? 'present' : 'absent'}. Origin: ${socket.handshake.headers.origin}. Path: ${socket.nsp.name}`); + // Пытаемся получить IP клиента, учитывая возможные заголовки от прокси + const clientIp = socket.handshake.headers['x-forwarded-for']?.split(',')[0].trim() || socket.handshake.address; + const originHeader = socket.handshake.headers.origin; + const socketPath = socket.nsp.name; + + console.log(`[BC Socket.IO Middleware] Auth attempt for socket ${socket.id} from IP ${clientIp}. Token ${token ? 'present' : 'absent'}. Origin: ${originHeader}. Path: ${socketPath}`); if (token) { try { @@ -125,29 +130,32 @@ io.use(async (socket, next) => { // --- ОБРАБОТЧИКИ СОБЫТИЙ SOCKET.IO --- io.on('connection', (socket) => { + const clientIp = socket.handshake.headers['x-forwarded-for']?.split(',')[0].trim() || socket.handshake.address; + const originHeader = socket.handshake.headers.origin; + const socketPath = socket.nsp.name; + if (socket.userData && socket.userData.userId) { - console.log(`[BC Socket.IO] Authenticated user ${socket.userData.username} (ID: ${socket.userData.userId}) connected with socket: ${socket.id} to path ${socket.nsp.name}`); + console.log(`[BC Socket.IO Connection] Authenticated user ${socket.userData.username} (ID: ${socket.userData.userId}) connected. Socket: ${socket.id}, IP: ${clientIp}, Origin: ${originHeader}, Path: ${socketPath}`); loggedInUsers[socket.id] = socket.userData; if (gameManager && typeof gameManager.handleRequestGameState === 'function') { gameManager.handleRequestGameState(socket, socket.userData.userId); } else { - console.error("[BC Socket.IO] CRITICAL: gameManager or handleRequestGameState not available on connect for authenticated user!"); + console.error("[BC Socket.IO Connection] CRITICAL: gameManager or handleRequestGameState not available for authenticated user!"); } } else { - console.log(`[BC Socket.IO] Unauthenticated user connected with socket: ${socket.id} to path ${socket.nsp.name}. No game state will be restored.`); + console.log(`[BC Socket.IO Connection] Unauthenticated user connected. Socket: ${socket.id}, IP: ${clientIp}, Origin: ${originHeader}, Path: ${socketPath}. No game state will be restored.`); } - // ... (остальные обработчики событий: logout, playerSurrender, createGame, и т.д. остаются как в вашей версии с логами) ... - // Копирую их из вашего предыдущего варианта для полноты: + // ... (остальные обработчики событий: logout, playerSurrender, createGame, и т.д. как в предыдущей версии) ... socket.on('logout', () => { const username = socket.userData?.username || 'UnknownUser'; const userId = socket.userData?.userId; - console.log(`[BC Socket.IO] 'logout' event from user ${username} (ID: ${userId}, Socket: ${socket.id})`); + console.log(`[BC Socket.IO 'logout'] Event from user ${username} (ID: ${userId}, Socket: ${socket.id})`); if (loggedInUsers[socket.id]) { delete loggedInUsers[socket.id]; } socket.userData = null; - console.log(`[BC Socket.IO] User ${username} (Socket: ${socket.id}) session data cleared on server due to 'logout' event.`); + console.log(`[BC Socket.IO 'logout'] User ${username} (Socket: ${socket.id}) session data cleared.`); }); socket.on('playerSurrender', () => { @@ -235,7 +243,7 @@ io.on('connection', (socket) => { socket.on('disconnect', (reason) => { const identifier = socket.userData?.userId; const username = socket.userData?.username || 'UnauthenticatedUser'; - console.log(`[BC Socket.IO] User ${username} (ID: ${identifier || 'N/A'}, Socket: ${socket.id}) disconnected. Reason: ${reason}.`); + console.log(`[BC Socket.IO Disconnect] User ${username} (ID: ${identifier || 'N/A'}, Socket: ${socket.id}) disconnected. Reason: ${reason}.`); if (identifier) { gameManager.handleDisconnect(socket.id, identifier); } @@ -250,27 +258,30 @@ const PORT = parseInt(process.env.BC_APP_PORT || '3200', 10); const HOSTNAME = process.env.BC_APP_HOSTNAME || '127.0.0.1'; if (isNaN(PORT)) { - console.error(`[BC Server FATAL] Некорректное значение для BC_APP_PORT: "${process.env.BC_APP_PORT}". Ожидается число.`); + console.error(`[BC Server FATAL] Invalid BC_APP_PORT: "${process.env.BC_APP_PORT}". Expected a number.`); process.exit(1); } server.listen(PORT, HOSTNAME, () => { - console.log(`[BC Server] Battle Club HTTP Application Server running at http://${HOSTNAME}:${PORT}`); + console.log(`[BC Server Startup] Battle Club HTTP Application Server running at http://${HOSTNAME}:${PORT}`); if (HOSTNAME === '127.0.0.1') { - console.log(`[BC Server] Server is listening on localhost only. This is suitable if a reverse proxy handles external traffic.`); + console.log(`[BC Server Startup] Server is listening on localhost only.`); } else if (HOSTNAME === '0.0.0.0') { - console.log(`[BC Server] Server is listening on all available network interfaces.`); + console.log(`[BC Server Startup] Server is listening on all available network interfaces.`); } else { - console.log(`[BC Server] Server is listening on a specific interface: ${HOSTNAME}.`); + console.log(`[BC Server Startup] Server is listening on a specific interface: ${HOSTNAME}.`); } - console.log(`[BC Server] Static files served from: ${publicPath}`); + console.log(`[BC Server Startup] Static files served from: ${publicPath}`); + console.log(`[BC.JS Startup] Socket.IO server effective path: ${io.path()}`); + console.log(`[BC.JS Startup] HTTP API effective CORS origin: ${app.get('env') === 'development' && !process.env.CORS_ORIGIN_CLIENT ? "'*'" : clientOrigin || 'NOT SET'}`); // Это немного упрощенный вывод, точнее в логах CONFIG + console.log(`[BC.JS Startup] Socket.IO effective CORS origin: ${io.opts.cors.origin === '*' ? "'*'" : io.opts.cors.origin || 'NOT SET'}`); }); process.on('unhandledRejection', (reason, promise) => { - console.error('[BC Server FATAL] Unhandled Rejection at:', promise, 'reason:', reason); + console.error('[BC Server FATAL UnhandledRejection] Reason:', reason, 'Promise:', promise); }); process.on('uncaughtException', (err) => { - console.error('[BC Server FATAL] Uncaught Exception:', err); + console.error('[BC Server FATAL UncaughtException] Error:', err); process.exit(1); }); \ No newline at end of file