平台层 Tripo 配置把 base_url 校验成绝对 http(s) 地址

- server-rs/crates/platform-tripo/src/common/config.rs:validate 用 url::Url 解析 base_url,缺 scheme(openapi.tripo3d.com)、非 http(s)(ftp://)与无 host 的值都在构造点按 Configuration 失败,不再拖到请求期变成传输层报错
- server-rs/crates/platform-tripo/src/common/config.rs:补用例覆盖缺 scheme / 非 http(s) / 非法 URL 被拒、前后带空白的合法地址放行
This commit is contained in:
2026-09-24 17:57:31 +08:00
parent 7a4ccb8bfe
commit b54ff06bc7
@@ -51,6 +51,9 @@ impl TripoSettings {
/// 校验配置自洽。
///
/// `base_url` 必须是绝对的 `http(s)` 地址:只会「非空」挡不住 `example.com` 这类少了
/// scheme 的写法,那种值要等到真正发请求时才失败,报错指向传输层而不是配置本身。
///
/// 字段都是公开的,调用方可以用结构体字面量绕过 [`TripoSettings::new`]
/// [`crate::TripoProviderClient::new`] 会再校验一次,保证真正发起请求的那一端
/// 拿到的永远是合法配置。
@@ -67,6 +70,23 @@ impl TripoSettings {
message: "base_url must not be blank".to_string(),
});
}
let base_url =
url::Url::parse(self.base_url.trim()).map_err(|error| TripoError::Configuration {
field: "base_url",
message: format!("base_url must be an absolute URL: {error}"),
})?;
if !matches!(base_url.scheme(), "http" | "https") {
return Err(TripoError::Configuration {
field: "base_url",
message: "base_url must use http or https".to_string(),
});
}
if base_url.host_str().is_none() {
return Err(TripoError::Configuration {
field: "base_url",
message: "base_url must include a host".to_string(),
});
}
if self.request_timeout.is_zero() {
return Err(TripoError::Configuration {
field: "request_timeout",
@@ -127,6 +147,29 @@ mod tests {
}
}
#[test]
fn base_url_must_be_an_absolute_http_url() {
for (label, base_url) in [
("缺 scheme", "openapi.tripo3d.com/v3"),
("非 http(s)", "ftp://openapi.tripo3d.com/v3"),
("不是 URL", "not-a-url"),
] {
let error = settings(Duration::from_secs(1), "key", base_url)
.validate()
.expect_err(&format!("{label} 必须被拒绝"));
assert!(matches!(error, TripoError::Configuration { .. }), "{error}");
}
// 前后带空白的合法地址仍然放行:先 trim 再校验,与取值口径一致。
settings(
Duration::from_secs(1),
"key",
" https://openapi.tripo3d.com/v3 ",
)
.validate()
.expect("带空白的合法地址应可校验通过");
}
#[test]
fn new_returns_ready_to_use_settings() {
let settings = TripoSettings::new(