Skip to content

feat: Add LAN WebUI support for remote browser control#3972

Open
szh1118 wants to merge 4 commits into
farion1231:mainfrom
szh1118:feature/lan-webui
Open

feat: Add LAN WebUI support for remote browser control#3972
szh1118 wants to merge 4 commits into
farion1231:mainfrom
szh1118:feature/lan-webui

Conversation

@szh1118

@szh1118 szh1118 commented Jun 9, 2026

Copy link
Copy Markdown

概述

增加了局域网 WebUI 支持,允许通过浏览器远程控制 cc-switch。

主要变更

后端

  • 新增独立 WebUI HTTP API 服务器 (src-tauri/src/webui.rs, 808 行)
  • 支持 Bearer token 认证,确保 LAN 访问安全
  • 暴露 50+ 管理 API 端点(providers/proxy/settings/usage/models)
  • 使用独立线程 + tokio runtime 确保服务持久运行
  • 支持 CORS,允许跨域浏览器访问

前端

  • 新增统一命令客户端 (src/lib/commandClient.ts, 208 行)
  • 运行时检测:Tauri 桌面环境 vs 浏览器环境
  • 透明切换 Tauri IPC ↔ HTTP API
  • 迁移 20+ 文件到统一 API 抽象层

使用方式

启动 WebUI 服务器

CC_SWITCH_WEBUI=1 \
CC_SWITCH_WEBUI_HOST=0.0.0.0 \
CC_SWITCH_WEBUI_PORT=15722 \
CC_SWITCH_WEBUI_TOKEN='your-random-token' \
./cc-switch

浏览器访问

http://<主机IP>:3000/?token=your-random-token

首次访问时带 ?token= 参数,浏览器会自动保存到 localStorage,后续访问无需再带。

环境变量

变量 说明 默认值
CC_SWITCH_WEBUI 启用 WebUI 服务器 false
CC_SWITCH_WEBUI_HOST 监听地址 127.0.0.1
CC_SWITCH_WEBUI_PORT 监听端口 15722
CC_SWITCH_WEBUI_TOKEN 认证 token(强烈推荐设置)

已验证功能

  • ✅ Provider 列表/切换/增删改
  • ✅ 代理启停/状态查询
  • ✅ 设置读写
  • ✅ 用量统计查询
  • ✅ 模型列表获取

安全性

  • 默认绑定 127.0.0.1,仅本地访问
  • LAN 绑定需显式设置 CC_SWITCH_WEBUI_HOST=0.0.0.0
  • 强制 Bearer token 认证(设置 CC_SWITCH_WEBUI_TOKEN 后)
  • CORS 设置为 *(可根据需要收紧)

相关提交

  • d52c572 feat(webui): add LAN browser control MVP
  • 59702bd fix(webui): use dedicated thread+tokio runtime to keep WebUI server alive
  • 183be5c feat(webui): add /api/models/fetch endpoint for browser model list fetching

🤖 Generated with Claude Code

claude added 3 commits June 9, 2026 20:00
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…live

The previous tauri::async_runtime::spawn dropped the WebUiServer handle,
causing the server to stop immediately after startup. Use std::thread::spawn
with its own tokio runtime and block forever to keep the server alive.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tching

Expose fetch_models_for_config command via HTTP API so browser clients
can fetch available models from providers. Also export commandClient object
from commandClient.ts to fix import errors.

Fixes:
- Add /api/models/fetch POST endpoint to webui.rs
- Add FetchModelsRequest struct
- Map fetch_models_for_config to /api/models/fetch in commandClient
- Export commandClient object with invoke/listen methods
- Update model-fetch.ts to use commandClient instead of direct Tauri invoke

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@szh1118 szh1118 force-pushed the feature/lan-webui branch from b74e2f0 to 183be5c Compare June 9, 2026 15:41
- Add /api/webui/start, /api/webui/stop, /api/webui/restart routes
- Add WebUI settings tab (enable/disable, port, host, token)
- Add dynamic start/stop/restart via Tauri commands
- Add static file serving with SPA fallback (ServeDir)
- Add WebUI documentation to README
- Add settings persistence (webui_enabled, port, host, token)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@farion1231

Copy link
Copy Markdown
Owner

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 06d9dee415

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/lib/commandClient.ts
Comment on lines +40 to +44
if (window.location.port === "15722") return window.location.origin;

const protocol = window.location.protocol || "http:";
const hostname = window.location.hostname || "127.0.0.1";
return `${protocol}//${hostname}:15722`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use the current origin for non-default WebUI ports

When the WebUI is served on any configured port other than 15722, the browser client loads from that port but all API calls are redirected back to http(s)://<host>:15722 by this fallback. For example, setting webuiPort/CC_SWITCH_WEBUI_PORT to 18000 makes http://host:18000/ render the app, then /api/settings, provider switches, etc. are fetched from port 15722 and fail unless another server happens to be running there. The production WebUI should use window.location.origin whenever it is being served by the embedded server, not only for the default port.

Useful? React with 👍 / 👎.

Comment thread src-tauri/src/webui.rs
Comment on lines +856 to +865
let dist_path = exe_dir
.as_ref()
.map(|dir| dir.join("dist"))
.filter(|p| p.exists())
.or_else(|| {
// Fallback: check workspace root during development
let cwd = std::env::current_dir().ok()?;
let workspace_dist = cwd.join("dist");
workspace_dist.exists().then_some(workspace_dist)
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Serve packaged frontend assets instead of exe_dir/dist

In a packaged Tauri build, frontendDist is embedded/bundled for the WebView and this commit does not add a bundle.resources entry that places a physical dist directory next to the executable. As a result, installed users won't have either exe_dir/dist or the development cwd/dist, so the WebUI starts in “API only” mode and http://<host>:15722/ cannot load the remote-control UI despite the feature being advertised as auto-starting in the built app.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants