fix(proxy-ui): accept IPv6 listen addresses in ProxyPanel validation

The backend already understands `::` -> `::1` and wraps IPv6 literals
in brackets (services/proxy.rs), but the panel's save-time validator
only accepted localhost, 0.0.0.0, and IPv4 dotted-quads. Users who
wanted to listen on an IPv6 loopback had to bypass the UI and edit
config directly.

Add an isValidIpv6 helper that requires at least one ':' and round-trips
through `new URL('http://[<addr>]/')` so the platform's built-in IPv6
parser does the heavy lifting (covers compressed `::`, full 8-group
form, zone IDs). Update the invalidAddress copy in zh / en / ja so the
error message reflects the new accepted set.
This commit is contained in:
Jason
2026-05-13 23:36:44 +08:00
parent 5d3d9067af
commit 3c35972548
4 changed files with 24 additions and 10 deletions
+21 -7
View File
@@ -119,22 +119,36 @@ export function ProxyPanel({
const handleSaveBasicConfig = async () => {
if (!globalConfig) return;
// 校验地址格式(简单的 IP 地址或 localhost 校验
// 校验地址格式(IPv4 / IPv6 字面量 / localhost
const addressTrimmed = listenAddress.trim();
const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
const isValidIpv4 = (addr: string): boolean =>
ipv4Regex.test(addr) &&
addr.split(".").every((n) => {
const num = parseInt(n, 10);
return num >= 0 && num <= 255;
});
// IPv6 字面量校验:必须含 `:` 且能在 [..] 包装后被 URL 解析器接受。
// 后端 (services/proxy.rs) 会把 `::` 改写成 `::1`,所以这里也接受 `::`。
const isValidIpv6 = (addr: string): boolean => {
if (!addr.includes(":")) return false;
try {
new URL(`http://[${addr}]/`);
return true;
} catch {
return false;
}
};
const isValidAddress =
addressTrimmed === "localhost" ||
addressTrimmed === "0.0.0.0" ||
(ipv4Regex.test(addressTrimmed) &&
addressTrimmed.split(".").every((n) => {
const num = parseInt(n);
return num >= 0 && num <= 255;
}));
isValidIpv4(addressTrimmed) ||
isValidIpv6(addressTrimmed);
if (!isValidAddress) {
toast.error(
t("proxy.settings.invalidAddress", {
defaultValue:
"地址无效,请输入有效的 IP 地址(如 127.0.0.1)或 localhost",
"地址无效,请输入 IPv4(如 127.0.0.1、IPv6(如 ::1或 localhost",
}),
);
return;
+1 -1
View File
@@ -2196,7 +2196,7 @@
"saveFailed": "Save failed: {{error}}"
},
"invalidPort": "Invalid port, please enter a number between 1024-65535",
"invalidAddress": "Invalid address, please enter a valid IP address (e.g. 127.0.0.1) or localhost",
"invalidAddress": "Invalid address. Enter an IPv4 (e.g. 127.0.0.1), IPv6 (e.g. ::1), or localhost",
"configSaved": "Routing configuration saved",
"configSaveFailed": "Failed to save configuration",
"restartRequired": "Restart routing service for address or port changes to take effect"
+1 -1
View File
@@ -2196,7 +2196,7 @@
"saveFailed": "保存に失敗しました: {{error}}"
},
"invalidPort": "無効なポートです。1024〜65535 の数値を入力してください",
"invalidAddress": "無効なアドレスです。有効な IP アドレス(例: 127.0.0.1)または localhost を入力してください",
"invalidAddress": "無効なアドレスです。IPv4(例: 127.0.0.1、IPv6(例: ::1)、または localhost を入力してください",
"configSaved": "ルーティング設定を保存しました",
"configSaveFailed": "設定の保存に失敗しました",
"restartRequired": "アドレスまたはポートの変更を反映するにはルーティングサービスの再起動が必要です"
+1 -1
View File
@@ -2196,7 +2196,7 @@
"saveFailed": "保存失败: {{error}}"
},
"invalidPort": "端口无效,请输入 1024-65535 之间的数字",
"invalidAddress": "地址无效,请输入有效的 IP 地址(如 127.0.0.1)或 localhost",
"invalidAddress": "地址无效,请输入 IPv4(如 127.0.0.1、IPv6(如 ::1或 localhost",
"configSaved": "路由配置已保存",
"configSaveFailed": "保存配置失败",
"restartRequired": "修改地址或端口后需要重启路由服务才能生效"