From b46acd75817fc7d30d592cb0107b281aa84f7e28 Mon Sep 17 00:00:00 2001 From: JSR Date: Sun, 5 Jul 2026 18:44:59 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E4=B8=BA=20SECTL=20Auth=20=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E9=93=BE=E8=B7=AF=E6=B7=BB=E5=8A=A0=E8=80=97=E6=97=B6?= =?UTF-8?q?=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 定位点击登录到浏览器弹出之间约 1 分钟延迟的来源,在前端 (handleOAuthLogin / getAuthorizationUrl) 与 Rust (oauth_start_callback_server) 各步骤加 +Nms 相对耗时日志。 Co-Authored-By: Claude --- src-tauri/src/commands/oauth_server.rs | 27 +++++++++++++++++++++++--- src/components/OAuth/OAuthLogin.tsx | 12 ++++++++++++ src/services/sectlAuth.ts | 11 ++++++++++- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src-tauri/src/commands/oauth_server.rs b/src-tauri/src/commands/oauth_server.rs index 726a951..8375aa7 100644 --- a/src-tauri/src/commands/oauth_server.rs +++ b/src-tauri/src/commands/oauth_server.rs @@ -36,12 +36,24 @@ pub async fn oauth_start_callback_server( app_handle: tauri::AppHandle, _state: State<'_, Arc>>, ) -> Result, String> { + let t0 = std::time::Instant::now(); + let log = |step: &str| { + println!( + "[OAuth Callback] {} +{}ms", + step, + t0.elapsed().as_millis() + ); + }; + log("oauth_start_callback_server enter"); + let mut shutdown_tx = OAUTH_SERVER_SHUTDOWN.lock().await; + log("after acquire shutdown lock"); // 如果服务器已经在运行,直接返回 URL if shutdown_tx.is_some() { let port = OAUTH_CALLBACK_PORT; let url = format!("http://127.0.0.1:{}/oauth/callback", port); + log("server already running, return early"); return Ok(IpcResponse::success(OAuthServerStartResult { url, port })); } @@ -51,19 +63,26 @@ pub async fn oauth_start_callback_server( let url_for_spawn = url.clone(); // 尝试绑定;若端口被占用,强杀占用进程后重试一次 + log("before TcpListener::bind"); let listener = match tokio::net::TcpListener::bind(addr).await { - Ok(l) => l, + Ok(l) => { + log("after TcpListener::bind (ok)"); + l + } Err(e) => { if e.kind() == std::io::ErrorKind::AddrInUse { println!( - "[OAuth Callback] 端口 {} 被占用,尝试强杀占用进程", - port + "[OAuth Callback] 端口 {} 被占用,尝试强杀占用进程 +{}ms", + port, + t0.elapsed().as_millis() ); if let Err(kill_err) = kill_processes_on_port(port) { eprintln!("[OAuth Callback] 强杀端口占用进程失败: {}", kill_err); } + log("after kill_processes_on_port"); // 给系统一点时间回收端口 tokio::time::sleep(std::time::Duration::from_millis(300)).await; + log("after sleep 300ms"); tokio::net::TcpListener::bind(addr) .await .map_err(|e| format!("绑定回调服务器端口 {} 失败: {}", port, e))? @@ -76,6 +95,7 @@ pub async fn oauth_start_callback_server( let (tx, rx) = oneshot::channel::<()>(); *shutdown_tx = Some(tx); drop(shutdown_tx); + log("after store shutdown tx"); let app_handle_clone = app_handle.clone(); @@ -95,6 +115,7 @@ pub async fn oauth_start_callback_server( } } }); + log("after tokio::spawn, returning"); Ok(IpcResponse::success(OAuthServerStartResult { url, port })) } diff --git a/src/components/OAuth/OAuthLogin.tsx b/src/components/OAuth/OAuthLogin.tsx index afd8af6..d25d271 100644 --- a/src/components/OAuth/OAuthLogin.tsx +++ b/src/components/OAuth/OAuthLogin.tsx @@ -127,12 +127,18 @@ export function OAuthLogin({ visible, onClose, onSuccess }: OAuthLoginProps) { } setLoading(true) + const t0 = performance.now() + const log = (step: string) => + console.log(`[OAuthLogin] ${step} +${Math.round(performance.now() - t0)}ms`) + log("handleOAuthLogin start") try { // 启动本地 HTTP 回调服务器 (端口 51267,被占用则强杀已有进程) const api = (window as any).api if (api && typeof api.oauthStartCallbackServer === "function") { + log("before oauthStartCallbackServer") const res = await api.oauthStartCallbackServer() + log(`after oauthStartCallbackServer success=${res?.success}`) if (!res?.success) { throw new Error(res?.message || "启动回调服务器失败") } @@ -142,19 +148,25 @@ export function OAuthLogin({ visible, onClose, onSuccess }: OAuthLoginProps) { } } + log("before getAuthorizationUrl") const authUrl = await sectlAuth.getAuthorizationUrl() + log(`after getAuthorizationUrl url=${authUrl.slice(0, 60)}...`) // 使用 Tauri shell 打开系统浏览器 + log("before open(authUrl)") await open(authUrl) + log("after open(authUrl)") // 设置超时 setTimeout(() => { if (loading && !completedRef.current) { + log("login timeout, stopping callback server") stopCallbackServer() setLoading(false) message.warning("登录超时,请重试") } }, 300000) } catch (error: any) { + log(`handleOAuthLogin error: ${error?.message}`) message.error(error.message || "登录失败") await stopCallbackServer() setLoading(false) diff --git a/src/services/sectlAuth.ts b/src/services/sectlAuth.ts index 211556e..ab0c114 100644 --- a/src/services/sectlAuth.ts +++ b/src/services/sectlAuth.ts @@ -120,9 +120,16 @@ class SectlAuthService { } async getAuthorizationUrl(scope?: string[]): Promise { + const t0 = performance.now() + const log = (step: string) => + console.log(`[sectlAuth.getAuthorizationUrl] ${step} +${Math.round(performance.now() - t0)}ms`) + const state = this.generateRandomState() + log("after generateRandomState") this.codeVerifier = await generateCodeVerifier() + log("after generateCodeVerifier") const codeChallenge = await generateCodeChallenge(this.codeVerifier) + log("after generateCodeChallenge") // 保存 code_verifier 到 localStorage,以便 deep link 回调时使用 localStorage.setItem("sectl_code_verifier", this.codeVerifier) @@ -140,7 +147,9 @@ class SectlAuthService { params.set("scope", scope.join(" ")) } - return `${SECTL_CONFIG.authUrl}/oauth/authorize?${params.toString()}` + const url = `${SECTL_CONFIG.authUrl}/oauth/authorize?${params.toString()}` + log("done") + return url } async authorize(scope?: string[]): Promise {