const https = require('https'); const http = require('http'); const io = require('socket.io-client'); console.log('🔍 详细测试WebSocket握手重定向机制'); console.log('='.repeat(60)); // 1. 手动模拟WebSocket握手请求 - HTTP阶段 async function testWebSocketHandshakeHTTP() { console.log('\n1️⃣ 测试WebSocket握手的HTTP阶段...'); return new Promise((resolve) => { console.log('📡 发送WebSocket握手请求到 HTTP (80端口)'); const options = { hostname: 'whaletownend.xinghangee.icu', port: 80, path: '/socket.io/?EIO=4&transport=websocket', method: 'GET', headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade', 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==', 'Sec-WebSocket-Version': '13', 'Origin': 'http://whaletownend.xinghangee.icu', 'User-Agent': 'websocket-handshake-test' }, timeout: 10000 }; const req = http.request(options, (res) => { console.log(`📊 HTTP响应状态码: ${res.statusCode}`); console.log('📋 响应头:'); Object.entries(res.headers).forEach(([key, value]) => { console.log(` ${key}: ${value}`); }); let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { if (data && data.length < 500) { console.log(`📄 响应内容: ${data}`); } console.log('\n📊 分析结果:'); if (res.statusCode === 301 || res.statusCode === 302) { console.log('✅ WebSocket握手请求被重定向!'); console.log(`🔄 重定向到: ${res.headers.location}`); console.log('💡 证明: WebSocket握手的HTTP阶段支持重定向'); } else if (res.statusCode === 101) { console.log('✅ WebSocket握手成功升级'); } else if (res.statusCode === 400) { console.log('❌ WebSocket握手失败 - 400错误'); } else { console.log(`⚠️ 意外的响应: ${res.statusCode}`); } resolve({ statusCode: res.statusCode, location: res.headers.location, isRedirect: res.statusCode === 301 || res.statusCode === 302 }); }); }); req.on('error', (error) => { console.log(`❌ HTTP请求失败: ${error.message}`); resolve({ error: error.message }); }); req.on('timeout', () => { console.log('❌ HTTP请求超时'); req.destroy(); resolve({ error: 'timeout' }); }); req.end(); }); } // 2. 测试Socket.IO客户端是否能自动处理重定向 async function testSocketIORedirectHandling() { console.log('\n2️⃣ 测试Socket.IO客户端重定向处理...'); const testConfigs = [ { name: 'WS协议 - 测试重定向', url: 'ws://whaletownend.xinghangee.icu/game', options: { transports: ['websocket'], timeout: 8000, forceNew: true } }, { name: 'HTTP协议 - 测试重定向', url: 'http://whaletownend.xinghangee.icu/game', options: { transports: ['websocket', 'polling'], timeout: 8000, forceNew: true } } ]; const results = []; for (const config of testConfigs) { console.log(`\n🧪 ${config.name}`); console.log(`📡 URL: ${config.url}`); const result = await new Promise((resolve) => { const socket = io(config.url, config.options); let resolved = false; // 监听连接事件 socket.on('connect', () => { if (!resolved) { resolved = true; console.log(' ✅ 连接成功'); console.log(` 📡 Socket ID: ${socket.id}`); console.log(` 🚀 传输方式: ${socket.io.engine.transport.name}`); console.log(` 🔗 最终URL: ${socket.io.uri}`); // 检查是否发生了协议升级 const originalProtocol = config.url.startsWith('ws://') ? 'ws' : 'http'; const finalProtocol = socket.io.uri.startsWith('wss://') ? 'wss' : socket.io.uri.startsWith('ws://') ? 'ws' : socket.io.uri.startsWith('https://') ? 'https' : 'http'; if (originalProtocol !== finalProtocol) { console.log(` 🔄 协议升级: ${originalProtocol}:// → ${finalProtocol}://`); } socket.disconnect(); resolve({ success: true, transport: socket.io.engine.transport.name, finalUrl: socket.io.uri, protocolChanged: originalProtocol !== finalProtocol }); } }); socket.on('connect_error', (error) => { if (!resolved) { resolved = true; console.log(` ❌ 连接失败: ${error.message}`); console.log(` 🔍 错误类型: ${error.type || 'unknown'}`); // 检查是否是重定向相关的错误 if (error.message.includes('redirect') || error.message.includes('301') || error.message.includes('302')) { console.log(' 💡 这可能是重定向处理问题'); } resolve({ success: false, error: error.message, type: error.type }); } }); // 超时处理 setTimeout(() => { if (!resolved) { resolved = true; socket.disconnect(); console.log(' ❌ 连接超时'); resolve({ success: false, error: 'timeout' }); } }, config.options.timeout); }); results.push({ config: config.name, ...result }); // 等待1秒再测试下一个 await new Promise(resolve => setTimeout(resolve, 1000)); } return results; } // 3. 测试不同客户端库的重定向行为 async function testRawWebSocketRedirect() { console.log('\n3️⃣ 测试原生WebSocket重定向行为...'); const WebSocket = require('ws'); return new Promise((resolve) => { console.log('📡 使用原生WebSocket连接 ws://whaletownend.xinghangee.icu/socket.io/?EIO=4&transport=websocket'); try { const ws = new WebSocket('ws://whaletownend.xinghangee.icu/socket.io/?EIO=4&transport=websocket'); ws.on('open', () => { console.log(' ✅ 原生WebSocket连接成功'); console.log(' 💡 说明: 重定向在WebSocket握手阶段被正确处理'); ws.close(); resolve({ success: true }); }); ws.on('error', (error) => { console.log(` ❌ 原生WebSocket连接失败: ${error.message}`); if (error.message.includes('Unexpected server response: 301') || error.message.includes('Unexpected server response: 302')) { console.log(' 💡 发现重定向响应,但WebSocket库未自动处理'); console.log(' 📝 说明: 需要客户端库支持重定向处理'); } resolve({ success: false, error: error.message }); }); ws.on('close', (code, reason) => { console.log(` 🔌 WebSocket关闭: ${code} - ${reason}`); }); } catch (error) { console.log(` ❌ WebSocket创建失败: ${error.message}`); resolve({ success: false, error: error.message }); } }); } async function runHandshakeRedirectTests() { console.log('开始WebSocket握手重定向测试...\n'); const httpResult = await testWebSocketHandshakeHTTP(); const socketIOResults = await testSocketIORedirectHandling(); const rawWSResult = await testRawWebSocketRedirect(); console.log('\n' + '='.repeat(60)); console.log('📊 WebSocket握手重定向测试结果'); console.log('='.repeat(60)); console.log(`1. WebSocket握手HTTP阶段: ${httpResult.isRedirect ? '✅ 支持重定向' : '❌ 无重定向'}`); if (httpResult.location) { console.log(` 重定向目标: ${httpResult.location}`); } console.log(`2. Socket.IO客户端处理:`); socketIOResults.forEach((result, index) => { const status = result.success ? '✅ 成功' : '❌ 失败'; console.log(` ${index + 1}. ${result.config}: ${status}`); if (result.protocolChanged) { console.log(` 协议升级: 是`); } if (result.error) { console.log(` 错误: ${result.error}`); } }); console.log(`3. 原生WebSocket: ${rawWSResult.success ? '✅ 成功' : '❌ 失败'}`); if (rawWSResult.error) { console.log(` 错误: ${rawWSResult.error}`); } console.log('\n💡 技术原理验证:'); if (httpResult.isRedirect) { console.log('✅ 验证: WebSocket握手的HTTP阶段确实支持重定向'); console.log('📝 机制: ws://先发HTTP GET请求(带Upgrade头) → 收到301/302 → 可以重定向'); } else { console.log('❌ 未检测到WebSocket握手重定向'); } const successfulSocketIO = socketIOResults.filter(r => r.success); if (successfulSocketIO.length > 0) { console.log('✅ Socket.IO客户端能够处理某些重定向场景'); } else { console.log('❌ Socket.IO客户端无法处理当前的重定向配置'); } console.log('\n🔧 修正后的准确表述:'); console.log('1. ✅ HTTP请求(包括WebSocket握手请求)支持301/302重定向'); console.log('2. ✅ WebSocket的"升级请求(HTTP层)"可以被重定向'); console.log('3. ✅ ws://先通过80端口发HTTP握手请求,再尝试升级为WebSocket'); console.log('4. ⚠️ 客户端库需要支持重定向处理才能正常工作'); process.exit(0); } runHandshakeRedirectTests().catch(console.error);