Closed
Conversation
Contributor
Reviewer's Guide为三个服务商(OpenFrp、SakuraFrp、ChmlFrp)新增内置的 FRP 内网穿透支持,包括一个新的 UI 页面、用于在各平台拉起服务商专用 frpc 二进制的 Tauri 命令,以及在多种操作系统/架构下打包的 frp 配置/模板和许可证文件。 从新的 FRP UI 启动 FRP 隧道的时序图sequenceDiagram
actor User
participant FRPView as FRPView
participant SystemApi as systemApi
participant Tauri as TauriRuntime
participant SysCmd as system_start_frp_tunnel
participant FrpcProc as Frpc_process
User ->> FRPView: Select provider, enter token and tunnelId
User ->> FRPView: Click startTunnel
FRPView ->> SystemApi: startFrpTunnel(provider, token, tunnelId)
SystemApi ->> Tauri: tauriInvoke start_frp_tunnel
Tauri ->> SysCmd: start_frp_tunnel(provider, token, tunnelId)
SysCmd ->> SysCmd: Detect OS and ARCH
SysCmd ->> SysCmd: Map os_name and arch_name
SysCmd ->> SysCmd: Build frpc_path under app_dir
alt frpc not found in app_dir
loop Up to 5 parent directories
SysCmd ->> SysCmd: Build candidate frpc_path
SysCmd ->> SysCmd: Check candidate_path.exists()
end
end
SysCmd ->> SysCmd: Validate frpc_path.exists()
alt provider is chmlfrp or openfrp
SysCmd ->> SysCmd: Build args -u token -p tunnelId
else provider is sakurafrp
SysCmd ->> SysCmd: Build args -f token:tunnelId
end
par Spawn frpc in new terminal window
alt Windows
SysCmd ->> FrpcProc: cmd.exe /c start cmd.exe /k frpc.exe args
else macOS
SysCmd ->> FrpcProc: open -a Terminal frpc args
else Linux
SysCmd ->> FrpcProc: xterm|gnome-terminal -e/-- frpc args
end
end
SysCmd -->> Tauri: Ok or error
Tauri -->> SystemApi: Ok or error
SystemApi -->> FRPView: Ok or error
alt success
FRPView ->> User: Toast 隧道启动成功
else error
FRPView ->> User: Toast 隧道启动失败
end
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your Experience在你的 dashboard 中可以:
Getting HelpOriginal review guide in EnglishReviewer's GuideAdds built-in FRP tunneling support for three providers (OpenFrp, SakuraFrp, ChmlFrp) including a new UI page, Tauri command to spawn provider-specific frpc binaries across platforms, and bundled frp config/templates and licenses for multiple OS/architectures. Sequence diagram for starting an FRP tunnel from the new FRP UIsequenceDiagram
actor User
participant FRPView as FRPView
participant SystemApi as systemApi
participant Tauri as TauriRuntime
participant SysCmd as system_start_frp_tunnel
participant FrpcProc as Frpc_process
User ->> FRPView: Select provider, enter token and tunnelId
User ->> FRPView: Click startTunnel
FRPView ->> SystemApi: startFrpTunnel(provider, token, tunnelId)
SystemApi ->> Tauri: tauriInvoke start_frp_tunnel
Tauri ->> SysCmd: start_frp_tunnel(provider, token, tunnelId)
SysCmd ->> SysCmd: Detect OS and ARCH
SysCmd ->> SysCmd: Map os_name and arch_name
SysCmd ->> SysCmd: Build frpc_path under app_dir
alt frpc not found in app_dir
loop Up to 5 parent directories
SysCmd ->> SysCmd: Build candidate frpc_path
SysCmd ->> SysCmd: Check candidate_path.exists()
end
end
SysCmd ->> SysCmd: Validate frpc_path.exists()
alt provider is chmlfrp or openfrp
SysCmd ->> SysCmd: Build args -u token -p tunnelId
else provider is sakurafrp
SysCmd ->> SysCmd: Build args -f token:tunnelId
end
par Spawn frpc in new terminal window
alt Windows
SysCmd ->> FrpcProc: cmd.exe /c start cmd.exe /k frpc.exe args
else macOS
SysCmd ->> FrpcProc: open -a Terminal frpc args
else Linux
SysCmd ->> FrpcProc: xterm|gnome-terminal -e/-- frpc args
end
end
SysCmd -->> Tauri: Ok or error
Tauri -->> SystemApi: Ok or error
SystemApi -->> FRPView: Ok or error
alt success
FRPView ->> User: Toast 隧道启动成功
else error
FRPView ->> User: Toast 隧道启动失败
end
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Contributor
There was a problem hiding this comment.
Hey - 我发现了 5 个问题,并且给出了一些整体性的反馈:
start_frp_tunnel在 Windows 分支中构建cmd.exe命令行时,没有对frpc路径或参数进行引号包裹,这会导致包含空格的路径出错;可以通过为可执行文件路径和任何用户提供的参数加上引号来提升健壮性。- FRP 配置文件
src-tauri/frpc.ini中似乎包含真实的服务器地址、用户和 token(ChmlFrpToken);建议移除或匿名化任何真实凭据,并通过用户配置加载这些信息,而不是直接提交到仓库。 - 针对每个 provider 的 FRP 二进制/配置查找逻辑在多个 match 分支以及向上目录搜索时都有重复;可以抽取一个小的辅助函数,只构建一次针对特定 provider 的
frpc路径,从而简化start_frp_tunnel,并减少不同分支随时间产生逻辑偏差的风险。
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The Windows branch of `start_frp_tunnel` builds a `cmd.exe` command line without quoting the `frpc` path or arguments, which will break for paths containing spaces and can be made more robust by wrapping the executable path and any user-provided arguments in quotes.
- The FRP config `src-tauri/frpc.ini` contains what looks like a real server address, user and token (`ChmlFrpToken`); consider removing or anonymizing any real credentials and loading this information from user configuration instead of committing it to the repo.
- The FRP binary/config lookup logic for each provider is duplicated in multiple match arms and again in the upward-directory search; extracting a small helper to build the provider-specific `frpc` path once would simplify `start_frp_tunnel` and reduce the chance of the branches diverging over time.
## Individual Comments
### Comment 1
<location path="src-tauri/src/commands/system.rs" line_range="346-347" />
<code_context>
Ok(())
}
+
+#[tauri::command]
+pub fn start_frp_tunnel(provider: String, token: String, tunnel_id: String) -> Result<(), String> {
+ // 确定系统和架构
+ let os = std::env::consts::OS;
</code_context>
<issue_to_address>
**🚨 issue (security):** Passing token and tunnel ID as CLI args exposes them in process lists; consider a safer way to pass secrets.
The FRP token and tunnel ID are always passed via CLI args in the base `command` and all platform-specific launchers. On most systems, process arguments are visible to other users (ps, Task Manager, etc.), so this can leak credentials. If FRP supports config files, env vars, or stdin for credentials, prefer those and avoid putting secrets on the command line.
</issue_to_address>
### Comment 2
<location path="src-tauri/src/commands/system.rs" line_range="451-453" />
<code_context>
+ #[cfg(target_os = "windows")]
+ {
+ // 在Windows上使用start命令打开新窗口
+ let frpc_path_str = frpc_path.to_str().unwrap();
+ // 转换为Windows风格的路径
+ let windows_path = frpc_path_str.replace('/', "\\");
+ // 构建命令参数
+ let mut cmd = std::process::Command::new("cmd.exe");
</code_context>
<issue_to_address>
**issue (bug_risk):** Avoid `to_str().unwrap()` on paths; handle non-UTF8 paths more defensively.
On Windows this will panic if `frpc_path` contains non‑UTF‑8 data, causing the command to crash. Prefer `to_string_lossy()` or explicitly handle the `None` case from `to_str()` and map it to your `Result<(), String>` instead of unwrapping.
</issue_to_address>
### Comment 3
<location path="src/views/FRPView.vue" line_range="14" />
<code_context>
+ </div>
+ <div class="form-row">
+ <label class="form-label">token</label>
+ <input type="text" class="form-input" placeholder="粘贴token" v-model="token" />
+ </div>
+ <div class="form-row">
</code_context>
<issue_to_address>
**🚨 issue (security):** Token is collected in a plain text field; consider treating it as a secret.
This field uses a standard `type="text"` input, so the token is fully visible on screen and may end up in browser autofill history. Using `type="password"` (optionally with a visibility toggle) would better protect the token from shoulder surfing and accidental exposure while still allowing copy/paste.
</issue_to_address>
### Comment 4
<location path="src/views/FRPView.vue" line_range="37-44" />
<code_context>
+const tunnelId = ref("");
+const { success, error } = useToast();
+
+async function startTunnel() {
+ if (!token.value || !tunnelId.value) {
+ error("请填写完整信息");
+ return;
+ }
+
+ try {
+ await startFrpTunnel(provider.value, token.value, tunnelId.value);
+ success("隧道启动成功");
+ } catch (err) {
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Consider disabling the button or handling concurrent clicks while the tunnel is starting.
Multiple rapid clicks on “启动隧道” will call `startFrpTunnel` in parallel and may start duplicate tunnels or surface confusing errors. Consider guarding with an `isStarting` flag to prevent re-entry (e.g., disable the button and/or show a loading state while the async call is in progress).
Suggested implementation:
```
const provider = ref("openfrp");
const token = ref("");
const tunnelId = ref("");
const { success, error } = useToast();
const isStarting = ref(false);
async function startTunnel() {
if (isStarting.value) {
// 防止重复点击导致并发请求
return;
}
if (!token.value || !tunnelId.value) {
error("请填写完整信息");
return;
}
isStarting.value = true;
try {
await startFrpTunnel(provider.value, token.value, tunnelId.value);
success("隧道启动成功");
} catch (err) {
error("隧道启动失败");
console.error(err);
} finally {
isStarting.value = false;
}
}
```
1. In the `<template>` for this view, bind the "启动隧道" button's `disabled` (and/or loading) state to `isStarting`, for example:
- `:disabled="isStarting"` or `:loading="isStarting"` depending on your UI library.
2. If you're using a custom button component (e.g. from Element Plus, Naive UI, etc.), follow its existing pattern for showing loading states to visually indicate that the tunnel is starting.
</issue_to_address>
### Comment 5
<location path="src-tauri/frpc.ini" line_range="1-7" />
<code_context>
+[common]
+server_addr = 127.0.0.1
+server_port = 7000
</code_context>
<issue_to_address>
**🚨 issue (security):** Committed FRP config contains concrete server address, user and token, which may be sensitive.
If these values (including any `user`/`token` in this file) are real credentials, they shouldn’t be committed. Please replace with clearly fake placeholders and load any secrets from environment or user input instead, to avoid accidental leakage.
</issue_to_address>Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Original comment in English
Hey - I've found 5 issues, and left some high level feedback:
- The Windows branch of
start_frp_tunnelbuilds acmd.execommand line without quoting thefrpcpath or arguments, which will break for paths containing spaces and can be made more robust by wrapping the executable path and any user-provided arguments in quotes. - The FRP config
src-tauri/frpc.inicontains what looks like a real server address, user and token (ChmlFrpToken); consider removing or anonymizing any real credentials and loading this information from user configuration instead of committing it to the repo. - The FRP binary/config lookup logic for each provider is duplicated in multiple match arms and again in the upward-directory search; extracting a small helper to build the provider-specific
frpcpath once would simplifystart_frp_tunneland reduce the chance of the branches diverging over time.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The Windows branch of `start_frp_tunnel` builds a `cmd.exe` command line without quoting the `frpc` path or arguments, which will break for paths containing spaces and can be made more robust by wrapping the executable path and any user-provided arguments in quotes.
- The FRP config `src-tauri/frpc.ini` contains what looks like a real server address, user and token (`ChmlFrpToken`); consider removing or anonymizing any real credentials and loading this information from user configuration instead of committing it to the repo.
- The FRP binary/config lookup logic for each provider is duplicated in multiple match arms and again in the upward-directory search; extracting a small helper to build the provider-specific `frpc` path once would simplify `start_frp_tunnel` and reduce the chance of the branches diverging over time.
## Individual Comments
### Comment 1
<location path="src-tauri/src/commands/system.rs" line_range="346-347" />
<code_context>
Ok(())
}
+
+#[tauri::command]
+pub fn start_frp_tunnel(provider: String, token: String, tunnel_id: String) -> Result<(), String> {
+ // 确定系统和架构
+ let os = std::env::consts::OS;
</code_context>
<issue_to_address>
**🚨 issue (security):** Passing token and tunnel ID as CLI args exposes them in process lists; consider a safer way to pass secrets.
The FRP token and tunnel ID are always passed via CLI args in the base `command` and all platform-specific launchers. On most systems, process arguments are visible to other users (ps, Task Manager, etc.), so this can leak credentials. If FRP supports config files, env vars, or stdin for credentials, prefer those and avoid putting secrets on the command line.
</issue_to_address>
### Comment 2
<location path="src-tauri/src/commands/system.rs" line_range="451-453" />
<code_context>
+ #[cfg(target_os = "windows")]
+ {
+ // 在Windows上使用start命令打开新窗口
+ let frpc_path_str = frpc_path.to_str().unwrap();
+ // 转换为Windows风格的路径
+ let windows_path = frpc_path_str.replace('/', "\\");
+ // 构建命令参数
+ let mut cmd = std::process::Command::new("cmd.exe");
</code_context>
<issue_to_address>
**issue (bug_risk):** Avoid `to_str().unwrap()` on paths; handle non-UTF8 paths more defensively.
On Windows this will panic if `frpc_path` contains non‑UTF‑8 data, causing the command to crash. Prefer `to_string_lossy()` or explicitly handle the `None` case from `to_str()` and map it to your `Result<(), String>` instead of unwrapping.
</issue_to_address>
### Comment 3
<location path="src/views/FRPView.vue" line_range="14" />
<code_context>
+ </div>
+ <div class="form-row">
+ <label class="form-label">token</label>
+ <input type="text" class="form-input" placeholder="粘贴token" v-model="token" />
+ </div>
+ <div class="form-row">
</code_context>
<issue_to_address>
**🚨 issue (security):** Token is collected in a plain text field; consider treating it as a secret.
This field uses a standard `type="text"` input, so the token is fully visible on screen and may end up in browser autofill history. Using `type="password"` (optionally with a visibility toggle) would better protect the token from shoulder surfing and accidental exposure while still allowing copy/paste.
</issue_to_address>
### Comment 4
<location path="src/views/FRPView.vue" line_range="37-44" />
<code_context>
+const tunnelId = ref("");
+const { success, error } = useToast();
+
+async function startTunnel() {
+ if (!token.value || !tunnelId.value) {
+ error("请填写完整信息");
+ return;
+ }
+
+ try {
+ await startFrpTunnel(provider.value, token.value, tunnelId.value);
+ success("隧道启动成功");
+ } catch (err) {
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Consider disabling the button or handling concurrent clicks while the tunnel is starting.
Multiple rapid clicks on “启动隧道” will call `startFrpTunnel` in parallel and may start duplicate tunnels or surface confusing errors. Consider guarding with an `isStarting` flag to prevent re-entry (e.g., disable the button and/or show a loading state while the async call is in progress).
Suggested implementation:
```
const provider = ref("openfrp");
const token = ref("");
const tunnelId = ref("");
const { success, error } = useToast();
const isStarting = ref(false);
async function startTunnel() {
if (isStarting.value) {
// 防止重复点击导致并发请求
return;
}
if (!token.value || !tunnelId.value) {
error("请填写完整信息");
return;
}
isStarting.value = true;
try {
await startFrpTunnel(provider.value, token.value, tunnelId.value);
success("隧道启动成功");
} catch (err) {
error("隧道启动失败");
console.error(err);
} finally {
isStarting.value = false;
}
}
```
1. In the `<template>` for this view, bind the "启动隧道" button's `disabled` (and/or loading) state to `isStarting`, for example:
- `:disabled="isStarting"` or `:loading="isStarting"` depending on your UI library.
2. If you're using a custom button component (e.g. from Element Plus, Naive UI, etc.), follow its existing pattern for showing loading states to visually indicate that the tunnel is starting.
</issue_to_address>
### Comment 5
<location path="src-tauri/frpc.ini" line_range="1-7" />
<code_context>
+[common]
+server_addr = 127.0.0.1
+server_port = 7000
</code_context>
<issue_to_address>
**🚨 issue (security):** Committed FRP config contains concrete server address, user and token, which may be sensitive.
If these values (including any `user`/`token` in this file) are real credentials, they shouldn’t be committed. Please replace with clearly fake placeholders and load any secrets from environment or user input instead, to avoid accidental leakage.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
提交前检查清单
提交前测试必读!!!.md并完成要求测试变更分类(必选其一)
feat新功能fixBug 修复docs文档/模板style代码格式(不影响功能)refactor重构(既不修复 bug 也不添加功能)perf性能优化test测试相关chore构建/CI/依赖/工具链revert回滚security安全修复影响范围(可多选)
前端 Frontend
后端 Backend
基础设施 Infrastructure
导入规范检查: 使用别名导入,避免相对路径
../变更详情
摘要
添加了3个提供商的frp(但目前只有中文)
动机/背景
让使用者可以在开服的同时方便地进行内网穿透
具体改动
界面变动(如适用)
QQ20260228-221100.mp4
QQ20260301-075954.mp4
关联 Issue
示例:
close/closes/closedClose #123fix/fixes/fixedFixes #123resolve/resolves/resolvedResolve #123ref/references/refsRef #123related/relates toRelated to #123part ofPart of #123see/see alsoSee #123reRe #123addressesAddresses #123implementsImplements #123mergesMerges #123自动化审查说明
sourcery-ai 及其他 code review 工具请务必进行中英双语审查与交流。
Note: Please ensure sourcery-ai and other tools perform bilingual (Chinese & English) review.
Summary by Sourcery
添加内置的 FRP 隧道支持,提供专用的 UI 和后端命令,并为多平台打包不同服务商的客户端/服务端配置。
新功能:
增强:
Original summary in English
Summary by Sourcery
Add built-in FRP tunneling support with a dedicated UI and backend command, bundling provider-specific client/server configs for multiple platforms.
New Features:
Enhancements: