feat: complete T-530 cmhub URL normalization
This commit is contained in:
+33
-2
@@ -9,6 +9,7 @@ import copy
|
||||
import json
|
||||
import os
|
||||
import urllib.error
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
|
||||
|
||||
@@ -129,6 +130,17 @@ def _deep_merge(defaults, loaded):
|
||||
return merged
|
||||
|
||||
|
||||
def _normalize_config_values(config):
|
||||
if not isinstance(config, dict):
|
||||
return config
|
||||
ai = config.get("ai")
|
||||
if isinstance(ai, dict):
|
||||
cmhub = ai.get("cmhub")
|
||||
if isinstance(cmhub, dict):
|
||||
cmhub["base_url"] = normalize_cmhub_base_url(cmhub.get("base_url", ""))
|
||||
return config
|
||||
|
||||
|
||||
def _assert_no_secrets(config):
|
||||
def visit(value, path):
|
||||
if isinstance(value, dict):
|
||||
@@ -247,6 +259,7 @@ def save_config(config, path=CONFIG_PATH) -> dict:
|
||||
"""Persist config to JSON and return the normalized config."""
|
||||
|
||||
normalized = _deep_merge(DEFAULT_CONFIG, config)
|
||||
_normalize_config_values(normalized)
|
||||
_assert_no_secrets(normalized)
|
||||
directory = os.path.dirname(os.path.abspath(path))
|
||||
if directory:
|
||||
@@ -268,6 +281,7 @@ def load_config(path=CONFIG_PATH) -> dict:
|
||||
except json.JSONDecodeError as exc:
|
||||
raise ConfigError(f"配置文件不是有效 JSON: {path}") from exc
|
||||
normalized = _deep_merge(DEFAULT_CONFIG, loaded)
|
||||
_normalize_config_values(normalized)
|
||||
_assert_no_secrets(normalized)
|
||||
return normalized
|
||||
|
||||
@@ -334,7 +348,7 @@ def cmhub_config(config=None) -> dict:
|
||||
if not isinstance(value, dict):
|
||||
raise ConfigError("ai.cmhub 必须是对象")
|
||||
merged = _deep_merge(DEFAULT_CONFIG["ai"]["cmhub"], value)
|
||||
merged["base_url"] = str(merged.get("base_url", "") or "").strip()
|
||||
merged["base_url"] = normalize_cmhub_base_url(merged.get("base_url", ""))
|
||||
merged["title_alias"] = str(merged.get("title_alias", "") or "").strip()
|
||||
merged["image_alias"] = str(merged.get("image_alias", "") or "").strip()
|
||||
merged["connect_timeout"] = int(merged.get("connect_timeout", 10) or 10)
|
||||
@@ -344,8 +358,25 @@ def cmhub_config(config=None) -> dict:
|
||||
return merged
|
||||
|
||||
|
||||
def normalize_cmhub_base_url(base_url) -> str:
|
||||
"""Return the cmhub gateway root URL without path/query/fragment."""
|
||||
|
||||
text = str(base_url or "").strip()
|
||||
if not text:
|
||||
return ""
|
||||
parts = urllib.parse.urlsplit(text)
|
||||
if parts.scheme and parts.netloc:
|
||||
return urllib.parse.urlunsplit((parts.scheme, parts.netloc, "", "", ""))
|
||||
if parts.netloc:
|
||||
return urllib.parse.urlunsplit((parts.scheme, parts.netloc, "", "", ""))
|
||||
without_query = text.split("?", 1)[0].split("#", 1)[0].strip().strip("/")
|
||||
if "://" not in without_query:
|
||||
return without_query.split("/", 1)[0]
|
||||
return text.rstrip("/")
|
||||
|
||||
|
||||
def cmhub_request_url(base_url, endpoint) -> str:
|
||||
base = str(base_url or "").strip().rstrip("/")
|
||||
base = normalize_cmhub_base_url(base_url)
|
||||
path = "/" + str(endpoint or "").strip().lstrip("/")
|
||||
if not base:
|
||||
return path
|
||||
|
||||
Reference in New Issue
Block a user