mirror of
https://github.com/qingchencloud/clawpanel.git
synced 2026-05-07 06:22:53 +08:00
fix: 修复系统诊断页面一键修复配对,解决 origin not allowed 握手失败
根本原因:Gateway WebSocket 服务检查 HTTP Origin 头,Tauri 应用的 origin (tauri://localhost / https://tauri.localhost) 不在 gateway.controlUi.allowedOrigins 白名单,导致 code 1008 拒绝握手。 修复内容: - pairing.rs: auto_pair_device 新增 patch_gateway_origins(),在写入 paired.json 的同时将 tauri://localhost 和 https://tauri.localhost 写入 openclaw.json gateway.controlUi.allowedOrigins - chat-debug.js: fixPairing 流程补充 origins 写入提示;success 后 触发主 wsClient.reconnect() 让主界面恢复正常;修复诊断建议去除 重复条件,合并 origin/端口 两种可能原因 - chat-debug.js: testWebSocket 1008 关闭时给出明确原因和解决方法 - ws-client.js: onclose 1008 时自动触发 _autoPairAndReconnect() 而非普通重连,实现主应用自愈
This commit is contained in:
@@ -88,9 +88,48 @@ pub fn auto_pair_device() -> Result<String, String> {
|
||||
|
||||
std::fs::write(&paired_path, new_content).map_err(|e| format!("写入 paired.json 失败: {e}"))?;
|
||||
|
||||
// 同步写入 controlUi.allowedOrigins,允许 Tauri 的 origin 连接 Gateway
|
||||
patch_gateway_origins();
|
||||
|
||||
Ok("设备配对成功".into())
|
||||
}
|
||||
|
||||
/// 将 Tauri 应用的 origin 写入 gateway.controlUi.allowedOrigins
|
||||
/// 避免 Gateway 因 origin not allowed 拒绝 WebSocket 握手
|
||||
fn patch_gateway_origins() {
|
||||
let config_path = crate::commands::openclaw_dir().join("openclaw.json");
|
||||
if !config_path.exists() {
|
||||
return;
|
||||
}
|
||||
let Ok(content) = std::fs::read_to_string(&config_path) else {
|
||||
return;
|
||||
};
|
||||
let Ok(mut config) = serde_json::from_str::<serde_json::Value>(&content) else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Tauri v2: macOS/Linux 用 tauri://localhost,Windows 用 https://tauri.localhost
|
||||
let origins = serde_json::json!(["tauri://localhost", "https://tauri.localhost", "http://localhost"]);
|
||||
|
||||
if let Some(obj) = config.as_object_mut() {
|
||||
let gateway = obj
|
||||
.entry("gateway")
|
||||
.or_insert_with(|| serde_json::json!({}));
|
||||
if let Some(gw) = gateway.as_object_mut() {
|
||||
let control_ui = gw
|
||||
.entry("controlUi")
|
||||
.or_insert_with(|| serde_json::json!({}));
|
||||
if let Some(cui) = control_ui.as_object_mut() {
|
||||
cui.insert("allowedOrigins".to_string(), origins);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(new_json) = serde_json::to_string_pretty(&config) {
|
||||
let _ = std::fs::write(&config_path, new_json);
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn check_pairing_status() -> Result<bool, String> {
|
||||
// 读取设备密钥
|
||||
|
||||
@@ -135,6 +135,13 @@ export class WsClient {
|
||||
this._flushPending()
|
||||
return
|
||||
}
|
||||
if (e.code === 1008 && !this._intentionalClose) {
|
||||
// origin not allowed — 自动写入 allowedOrigins 后再重连
|
||||
console.log('[ws] origin not allowed (1008),尝试自动修复...')
|
||||
this._setConnected(false, 'reconnecting', 'origin not allowed,修复中...')
|
||||
this._autoPairAndReconnect()
|
||||
return
|
||||
}
|
||||
this._setConnected(false)
|
||||
this._gatewayReady = false
|
||||
this._handshaking = false
|
||||
|
||||
@@ -238,7 +238,7 @@ function renderDebugInfo(el, info) {
|
||||
html += `<li style="color:var(--error);margin-bottom:6px">❌ 设备密钥生成失败,请检查 Rust 后端日志</li>`
|
||||
}
|
||||
if (!info.wsClient.connected && info.services?.length > 0 && info.services[0]?.running) {
|
||||
html += `<li style="color:var(--warning);margin-bottom:6px">⚠️ Gateway 已启动但 WebSocket 未连接,请检查端口 ${info.config?.gateway?.port || 18789} 是否被占用</li>`
|
||||
html += `<li style="color:var(--warning);margin-bottom:6px">⚠️ Gateway 运行中但 WebSocket 未连接,常见原因:<strong>origin not allowed</strong>(Tauri origin 未在白名单)或端口 ${info.config?.gateway?.port || 18789} 被占用。点击“一键修复配对”可自动修复 origin 问题</li>`
|
||||
}
|
||||
if (info.wsClient.connected && !info.wsClient.gatewayReady) {
|
||||
html += `<li style="color:var(--warning);margin-bottom:6px">⚠️ WebSocket 已连接但握手未完成,请检查 token 是否正确</li>`
|
||||
@@ -351,7 +351,10 @@ function testWebSocket(page) {
|
||||
|
||||
testWs.onclose = (e) => {
|
||||
addLog(`🔌 连接关闭 - Code: ${e.code}, Reason: ${e.reason || '(空)'}`)
|
||||
if (e.code === 4001) {
|
||||
if (e.code === 1008) {
|
||||
addLog(`❌ origin not allowed (1008) - Gateway 拒绝了当前应用的 origin`)
|
||||
addLog(`💡 解决方法:点击“一键修复配对”,将自动将 tauri://localhost 加入白名单并重启 Gateway`)
|
||||
} else if (e.code === 4001) {
|
||||
addLog(`❌ 认证失败 (4001) - Token 可能不正确`)
|
||||
} else if (e.code === 1006) {
|
||||
addLog(`⚠️ 异常关闭 (1006) - 可能是网络问题或 Gateway 主动断开`)
|
||||
@@ -475,10 +478,11 @@ async function fixPairing(page) {
|
||||
try {
|
||||
addLog('🔧 开始修复配对问题...')
|
||||
|
||||
// 1. 修改配置禁用配对
|
||||
addLog('📝 修改配置文件,禁用配对要求...')
|
||||
// 1. 写入 paired.json + controlUi.allowedOrigins
|
||||
addLog('📝 正在写入设备配对信息 + Gateway origin 白名单...')
|
||||
const result = await api.autoPairDevice()
|
||||
addLog(`✅ ${result}`)
|
||||
addLog('✅ 已将 tauri://localhost 加入 gateway.controlUi.allowedOrigins')
|
||||
|
||||
// 2. 重启 Gateway
|
||||
addLog('🔄 重启 Gateway 服务...')
|
||||
@@ -529,11 +533,19 @@ async function fixPairing(page) {
|
||||
if (msg.type === 'res' && msg.id?.startsWith('connect-')) {
|
||||
if (msg.ok) {
|
||||
addLog('🎉 握手成功!配对问题已修复!')
|
||||
addLog('💡 提示:现在可以正常使用 WebSocket 功能了')
|
||||
ws.close()
|
||||
addLog('💡 正在重新建立主应用 WebSocket 连接...')
|
||||
ws.close(1000)
|
||||
// 触发主应用的 wsClient 重连,让主界面正常工作
|
||||
wsClient.reconnect()
|
||||
setTimeout(() => loadDebugInfo(page), 2000)
|
||||
} else {
|
||||
addLog(`❌ 握手失败: ${msg.error?.message || '未知错误'}`)
|
||||
addLog('💡 建议:请手动重启 Gateway 或联系技术支持')
|
||||
const errMsg = msg.error?.message || msg.error?.code || '未知错误'
|
||||
addLog(`❌ 握手失败: ${errMsg}`)
|
||||
if (errMsg.includes('origin not allowed')) {
|
||||
addLog('💡 原因:Gateway 拒绝了当前应用的 origin,需要重启 Gateway 再试')
|
||||
} else {
|
||||
addLog('💡 建议:请手动前往“服务管理”页面重启 Gateway')
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -542,11 +554,14 @@ async function fixPairing(page) {
|
||||
}
|
||||
|
||||
ws.onerror = () => {
|
||||
addLog('❌ WebSocket 连接失败')
|
||||
addLog('❌ WebSocket 连接失败,请确认 Gateway 已在运行')
|
||||
}
|
||||
|
||||
ws.onclose = (e) => {
|
||||
if (e.code !== 1000) {
|
||||
if (e.code === 1008) {
|
||||
addLog(`⚠️ 连接被拒绝 (1008) - Gateway 拒绝了当前 origin`)
|
||||
addLog('💡 该问题应已被本次修复流程处理,请再次点击“一键修复配对”')
|
||||
} else if (e.code !== 1000) {
|
||||
addLog(`⚠️ 连接关闭 - Code: ${e.code}`)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user