Skip to content

Commit 6cfa173

Browse files
committed
fix(ostool): interpret legacy bare IP addresses as http for board server
1 parent 316a2d7 commit 6cfa173

4 files changed

Lines changed: 44 additions & 5 deletions

File tree

README.en.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ Use the TUI editor to update it:
317317
ostool board config
318318
```
319319

320-
`server` must be a complete URL including `http://` or `https://`; the optional `port` overrides the URL port. Project-local `.board.toml` `server` / `port` fields still apply to `ostool board run`, with precedence lower than CLI flags and higher than the global config.
320+
`server` should be a complete URL including `http://` or `https://`; the optional `port` overrides the URL port. For legacy LAN configurations, a bare IPv4 or IPv6 address is interpreted as `http://`; bare host names are not supported, and the removed `server_ip` field is not restored. Project-local `.board.toml` `server` / `port` fields still apply to `ostool board run`, with precedence lower than CLI flags and higher than the global config.
321321

322322
### Public board authentication
323323

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ auth_mode = "disabled"
314314
ostool board config
315315
```
316316

317-
`server` 必须是包含 `http://``https://` 的完整 URL;可选的 `port` 会覆盖 URL 中的端口。项目级 `.board.toml` 中的 `server` / `port` 仍可用于 `ostool board run`,其优先级低于命令行参数,高于全局配置。
317+
`server` 应使用包含 `http://``https://` 的完整 URL;可选的 `port` 会覆盖 URL 中的端口。为兼容旧的局域网配置,裸 IPv4 或 IPv6 地址会自动补为 `http://`;不支持无 scheme 的主机名,也不恢复已移除的 `server_ip` 字段。项目级 `.board.toml` 中的 `server` / `port` 仍可用于 `ostool board run`,其优先级低于命令行参数,高于全局配置。
318318

319319
### 公网开发板认证
320320

docs/api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
本文根据当前 `ostool` 客户端实现整理认证网关和开发板服务的调用接口;不包含 `ostool-server` 管理后台的 `/api/v1/admin/...` 接口。
44

5-
服务地址来自全局或项目配置中的 `board.server`(完整 URL),可被命令行 `--server` 覆盖;可选的 `board.port``--port` 用于覆盖 URL 中的端口。认证网关和 board API 使用同一个 Base URL。
5+
服务地址来自全局或项目配置中的 `board.server`(完整 URL),可被命令行 `--server` 覆盖;可选的 `board.port``--port` 用于覆盖 URL 中的端口。为兼容旧的局域网配置,`board.server` 为裸 IPv4 或 IPv6 地址时客户端自动补为 `http://`;无 scheme 的主机名不支持,已移除的 `server_ip` 字段也不会恢复。认证网关和 board API 使用同一个 Base URL。
66

77
- `auth_mode = "required"` 时,`board.server` 必须使用 HTTPS,所有请求携带下文描述的 Bearer Token;
88
- `auth_mode = "disabled"`(默认)时通常使用 HTTP,不会发送认证 Header,适合局域网直连 `ostool-server`

ostool/src/board/global_config.rs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::{
22
env, fs,
3+
net::IpAddr,
34
path::{Path, PathBuf},
45
};
56

@@ -26,8 +27,17 @@ pub struct BoardEndpoint {
2627

2728
impl BoardEndpoint {
2829
pub fn new(server: &str, port: Option<u16>, auth_mode: AuthMode) -> anyhow::Result<Self> {
29-
let mut base_url =
30-
Url::parse(server).with_context(|| format!("invalid board server URL `{server}`"))?;
30+
let server = server.trim();
31+
// Before `board.server` became a complete URL, LAN configurations used a
32+
// bare IP address. Keep that specific legacy form working by treating it
33+
// as HTTP; host names and all new configurations must include a scheme.
34+
let server_url = match server.parse::<IpAddr>() {
35+
Ok(IpAddr::V4(_)) => format!("http://{server}"),
36+
Ok(IpAddr::V6(_)) => format!("http://[{server}]"),
37+
Err(_) => server.to_string(),
38+
};
39+
let mut base_url = Url::parse(&server_url)
40+
.with_context(|| format!("invalid board server URL `{server}`"))?;
3141
if !matches!(base_url.scheme(), "http" | "https") {
3242
bail!("board server URL must use http or https");
3343
}
@@ -244,6 +254,35 @@ mod tests {
244254
);
245255
}
246256

257+
#[test]
258+
fn resolve_endpoint_accepts_legacy_bare_ip_as_http() {
259+
let config = BoardGlobalConfig {
260+
server: "192.0.2.10".into(),
261+
port: Some(9000),
262+
auth_mode: AuthMode::Disabled,
263+
};
264+
265+
assert_eq!(
266+
config
267+
.resolve_endpoint(None, None)
268+
.unwrap()
269+
.base_url
270+
.as_str(),
271+
"http://192.0.2.10:9000/"
272+
);
273+
}
274+
275+
#[test]
276+
fn endpoint_wraps_legacy_bare_ipv6_address() {
277+
assert_eq!(
278+
super::BoardEndpoint::new("2001:db8::10", Some(9000), AuthMode::Disabled)
279+
.unwrap()
280+
.base_url
281+
.as_str(),
282+
"http://[2001:db8::10]:9000/"
283+
);
284+
}
285+
247286
#[test]
248287
fn required_authentication_requires_https() {
249288
let config = BoardGlobalConfig {

0 commit comments

Comments
 (0)