Files
whale-town-end/test_redirect_and_websocket.js
moyin 38f9f81b6c test:添加WebSocket连接诊断和测试工具集
- test_zulip.js: Zulip集成功能的端到端测试脚本
- full_diagnosis.js: 全面的WebSocket连接诊断工具
- test_protocol_difference.js: 不同协议(ws/wss/http/https)的对比测试
- test_redirect_and_websocket.js: HTTP重定向和WebSocket升级测试
- test_websocket_handshake_redirect.js: WebSocket握手重定向机制验证
- websocket_with_redirect_support.js: 支持重定向的WebSocket连接实现

提供完整的WebSocket连接问题诊断和解决方案
2026-01-05 11:16:52 +08:00

205 lines
6.5 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const https = require('https');
const http = require('http');
const io = require('socket.io-client');
console.log('🔍 测试HTTP重定向和WebSocket配置');
console.log('='.repeat(50));
// 1. 测试HTTP重定向
async function testHttpRedirect() {
console.log('\n1⃣ 测试HTTP重定向...');
return new Promise((resolve) => {
const options = {
hostname: 'whaletownend.xinghangee.icu',
port: 80,
path: '/',
method: 'GET',
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}`);
});
if (res.statusCode === 301 || res.statusCode === 302) {
console.log('✅ HTTP重定向配置正确');
console.log(`🔄 重定向到: ${res.headers.location}`);
} else if (res.statusCode === 200) {
console.log('⚠️ HTTP没有重定向直接返回内容');
} else {
console.log(`❌ HTTP重定向异常: ${res.statusCode}`);
}
resolve({ statusCode: res.statusCode, location: res.headers.location });
});
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. 测试WebSocket升级映射
async function testWebSocketUpgradeMapping() {
console.log('\n2⃣ 测试WebSocket升级映射...');
// 检查nginx是否有$connection_upgrade映射
return new Promise((resolve) => {
const options = {
hostname: 'whaletownend.xinghangee.icu',
port: 443,
path: '/socket.io/?EIO=4&transport=websocket',
method: 'GET',
headers: {
'Upgrade': 'websocket',
'Connection': 'Upgrade',
'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==',
'Sec-WebSocket-Version': '13',
'Origin': 'https://whaletownend.xinghangee.icu'
},
timeout: 8000
};
const req = https.request(options, (res) => {
console.log(`📊 WebSocket握手状态码: ${res.statusCode}`);
console.log('📋 WebSocket响应头:');
Object.entries(res.headers).forEach(([key, value]) => {
console.log(` ${key}: ${value}`);
});
if (res.statusCode === 101) {
console.log('✅ WebSocket升级成功');
} else if (res.statusCode === 400) {
console.log('❌ WebSocket升级失败 - 400错误');
console.log('💡 可能缺少 $connection_upgrade 映射');
} else if (res.statusCode === 502) {
console.log('❌ WebSocket升级失败 - 502错误');
console.log('💡 后端连接问题');
} else {
console.log(`❌ WebSocket升级失败 - ${res.statusCode}错误`);
}
resolve({ statusCode: res.statusCode });
});
req.on('error', (error) => {
console.log(`❌ WebSocket握手失败: ${error.message}`);
resolve({ error: error.message });
});
req.on('timeout', () => {
console.log('❌ WebSocket握手超时');
req.destroy();
resolve({ error: 'timeout' });
});
req.end();
});
}
// 3. 测试WS协议是否能通过重定向工作
async function testWSProtocolWithRedirect() {
console.log('\n3⃣ 测试WS协议重定向...');
return new Promise((resolve) => {
console.log('🧪 尝试连接 ws://whaletownend.xinghangee.icu/game');
const socket = io('ws://whaletownend.xinghangee.icu/game', {
transports: ['websocket'],
timeout: 8000,
forceNew: true
});
let resolved = false;
const timeout = setTimeout(() => {
if (!resolved) {
resolved = true;
socket.disconnect();
console.log(' ❌ WS协议连接超时');
resolve({ success: false, error: 'timeout' });
}
}, 8000);
socket.on('connect', () => {
if (!resolved) {
resolved = true;
clearTimeout(timeout);
console.log(' ✅ WS协议连接成功通过重定向');
console.log(` 📡 Socket ID: ${socket.id}`);
console.log(` 🔗 实际URL: ${socket.io.uri}`);
socket.disconnect();
resolve({ success: true, actualUrl: socket.io.uri });
}
});
socket.on('connect_error', (error) => {
if (!resolved) {
resolved = true;
clearTimeout(timeout);
console.log(` ❌ WS协议连接失败: ${error.message}`);
console.log(` 🔍 错误详情: ${error.description?.message || 'N/A'}`);
resolve({ success: false, error: error.message });
}
});
});
}
async function runRedirectTests() {
const httpResult = await testHttpRedirect();
const websocketResult = await testWebSocketUpgradeMapping();
const wsProtocolResult = await testWSProtocolWithRedirect();
console.log('\n' + '='.repeat(50));
console.log('📊 重定向和WebSocket测试结果');
console.log('='.repeat(50));
console.log(`1. HTTP重定向: ${httpResult.statusCode === 301 || httpResult.statusCode === 302 ? '✅ 配置正确' : '❌ 未配置或异常'}`);
if (httpResult.location) {
console.log(` 重定向目标: ${httpResult.location}`);
}
console.log(`2. WebSocket升级: ${websocketResult.statusCode === 101 ? '✅ 正常' : '❌ 失败'}`);
console.log(`3. WS协议重定向: ${wsProtocolResult.success ? '✅ 工作' : '❌ 不工作'}`);
console.log('\n💡 分析结果:');
if (httpResult.statusCode === 301 || httpResult.statusCode === 302) {
console.log('✅ HTTP重定向配置正确');
} else {
console.log('❌ 缺少HTTP重定向配置');
console.log('🔧 需要添加HTTP server块进行重定向');
}
if (websocketResult.statusCode !== 101) {
console.log('❌ WebSocket升级配置有问题');
console.log('🔧 需要检查nginx配置中的:');
console.log(' 1. map $http_upgrade $connection_upgrade 映射');
console.log(' 2. proxy_set_header Upgrade $http_upgrade');
console.log(' 3. proxy_set_header Connection $connection_upgrade');
}
if (!wsProtocolResult.success) {
console.log('❌ WS协议无法通过重定向工作');
console.log('💡 原因: WebSocket协议升级发生在TCP层无法像HTTP那样重定向');
console.log('📝 解决方案: 客户端应该直接使用WSS协议');
}
process.exit(0);
}
runRedirectTests().catch(console.error);