feat: v1.5.6 — 「打开 Gitea」按钮链接可显式配置
远程访问时 CGI/代理环境常常无法可靠转发 Host 头(fnOS CGI 里 $HTTP_HOST 可能为空、Referer 被剥离),导致自动推断 出的'真实主机'就是面板本机的 127.0.0.1,按钮指向 localhost 没法用。 新增设置「打开 Gitea 链接」(cfg.open_url),按钮地址优先级: 1. 环境变量 GITEA_URL 2. cfg.open_url(本次新增,留空走推断) 3. cfg.gitea_host + 推断(XFH/Host/Referer) - UI:Gitea 与同步设置卡片里新增「打开 Gitea 链接」输入框 (含「保存」按钮,placeholder 提示一般不用填) - 校验:必须带协议头(http/https)、不能含路径;非法值拒绝 - /api/settings 暴露 open_url - 留空时维持原有自动推断行为,向后兼容 - manifest 1.5.5 → 1.5.6
This commit is contained in:
@@ -71,7 +71,8 @@ ENV["GIT_TERMINAL_PROMPT"] = "0"
|
||||
# ---------------- 应用设置(settings.json) ----------------
|
||||
cfg = {"gitea_user": LEGACY_GITEA_USER, "gitea_pass": "", "auto_create": True,
|
||||
"interval": DEFAULT_INTERVAL, "gitea_host": DEFAULT_GITEA_HOST,
|
||||
"max_workers": DEFAULT_WORKERS, "max_retries": DEFAULT_MAX_RETRIES}
|
||||
"max_workers": DEFAULT_WORKERS, "max_retries": DEFAULT_MAX_RETRIES,
|
||||
"open_url": ""} # 「打开 Gitea」按钮专用链接(留空则用 gitea_host + 自动推断)
|
||||
|
||||
|
||||
def norm_gitea_host(h):
|
||||
@@ -98,11 +99,15 @@ def gitea_host():
|
||||
|
||||
|
||||
def gitea_ui(host_header="", referer="", xfwd_host=""):
|
||||
"""「打开 Gitea」按钮地址:把 127.0.0.1/localhost 替换成真实远程主机名。
|
||||
推断顺序:X-Forwarded-Host(CGI 转发) > Host > Referer(浏览器自带)。
|
||||
注意:仅当推断出的真实主机名不是 loopback 时才替换(本地直连保持原样)。"""
|
||||
if GITEA_URL_ENV:
|
||||
return GITEA_URL_ENV
|
||||
"""「打开 Gitea」按钮地址。
|
||||
优先级:环境变量 GITEA_URL > 配置 open_url > gitea_host(自动推断替换)。
|
||||
自动推断顺序:X-Forwarded-Host > Host > Referer,仅当真实主机非 loopback 时替换 gitea_host。"""
|
||||
env_url = GITEA_URL_ENV
|
||||
if env_url:
|
||||
return env_url
|
||||
ou = (cfg.get("open_url") or "").strip()
|
||||
if ou:
|
||||
return ou
|
||||
base = gitea_host()
|
||||
real = (xfwd_host or host_header or "").split(":")[0].strip()
|
||||
if not real and referer:
|
||||
@@ -110,7 +115,7 @@ def gitea_ui(host_header="", referer="", xfwd_host=""):
|
||||
if m:
|
||||
real = m.group(1)
|
||||
if not real or real in ("127.0.0.1", "localhost", "0.0.0.0", "::1"):
|
||||
return base # 本地/无法推断,保留 gitea_host 原值
|
||||
return base
|
||||
try:
|
||||
p = urlsplit(base)
|
||||
if p.hostname in ("127.0.0.1", "localhost", "0.0.0.0", "::1", ""):
|
||||
@@ -184,6 +189,12 @@ def load_settings():
|
||||
h = norm_gitea_host(d.get("gitea_host"))
|
||||
if h:
|
||||
cfg["gitea_host"] = h
|
||||
# open_url 校验:必须是 http(s) URL 且无路径
|
||||
ou = d.get("open_url")
|
||||
if isinstance(ou, str):
|
||||
cfg["open_url"] = norm_gitea_host(ou.strip()) or ""
|
||||
else:
|
||||
cfg["open_url"] = str(ou or "").strip() or cfg.get("open_url", "")
|
||||
except Exception:
|
||||
pass
|
||||
write_gitcreds()
|
||||
@@ -1309,6 +1320,11 @@ PAGE_SETTINGS = """
|
||||
<button class="b-mini" onclick="saveGitea(true)">保存</button>
|
||||
</div>
|
||||
<div class="tip" id="giteaUrlTip"></div>
|
||||
<label class="flabel" style="margin-top:18px">「打开 Gitea」按钮链接<span class="sub">远程访问时若按钮打不开,留空自动推断或填入你的可访问地址</span></label>
|
||||
<div class="addrow">
|
||||
<input id="openUrl" placeholder="留空则自动推断(一般不用填)" autocomplete="off">
|
||||
<button class="b-mini" onclick="saveOpenUrl()">保存</button>
|
||||
</div>
|
||||
<div class="optbox">
|
||||
<div class="optrow">
|
||||
<label class="switch"><input type="checkbox" id="swAuto" onchange="saveAuto()"><span class="slider"></span></label>
|
||||
@@ -1386,6 +1402,7 @@ async function refresh(){
|
||||
document.getElementById('giteaPass').placeholder=s.gitea_pass_set
|
||||
?'Gitea 密码(已设置;留空保存可清除)':'Gitea 密码(私有仓库必填)';
|
||||
document.getElementById('giteaUrlTip').textContent='「打开 Gitea」按钮地址:'+(s.gitea_url||'—')+'(随访问地址自动适配);密码只保存在 NAS 本地,仅用于读取私有仓库。';
|
||||
document.getElementById('openUrl').value=s.open_url||'';
|
||||
document.getElementById('swAuto').checked=!!s.auto_create;
|
||||
const iv=document.getElementById('syncInterval');
|
||||
iv.value=s.interval||10;iv.min=s.min_interval||5;iv.max=s.max_interval||86400;
|
||||
@@ -1526,6 +1543,12 @@ async function saveGitea(withPass){
|
||||
if(withPass)document.getElementById('giteaPass').value='';
|
||||
refresh();
|
||||
}
|
||||
async function saveOpenUrl(){
|
||||
const v=document.getElementById('openUrl').value.trim();
|
||||
const r=await (await fetch('api/settings/save',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({open_url:v})})).json();
|
||||
showMsg('msgCfg',r.msg||JSON.stringify(r),!!r.ok);
|
||||
refresh();
|
||||
}
|
||||
async function saveAuto(){
|
||||
const auto_create=document.getElementById('swAuto').checked;
|
||||
const r=await (await fetch('api/settings/save',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({auto_create})})).json();
|
||||
@@ -1713,6 +1736,7 @@ class Handler(BaseHTTPRequestHandler):
|
||||
"max_retries": max_retries(),
|
||||
"retry_interval": RETRY_INTERVAL,
|
||||
"gitea_host": gitea_host(),
|
||||
"open_url": cfg.get("open_url", ""),
|
||||
"gitea_url": gitea_ui(
|
||||
self.headers.get("Host"),
|
||||
self.headers.get("Referer"),
|
||||
@@ -1751,6 +1775,15 @@ class Handler(BaseHTTPRequestHandler):
|
||||
self._json({"ok": False, "msg": "Gitea 地址不合法,应类似 http://127.0.0.1:3000"})
|
||||
return
|
||||
new_host = h
|
||||
if "open_url" in data:
|
||||
v = (data.get("open_url") or "").strip()
|
||||
if v:
|
||||
if "://" not in v:
|
||||
self._json({"ok": False, "msg": "「打开 Gitea 链接」必须带协议头,如 http://nas.local:3000 或 https://..."})
|
||||
return
|
||||
if not norm_gitea_host(v):
|
||||
self._json({"ok": False, "msg": "「打开 Gitea 链接」格式不合法,应类似 http://nas.local:3000(留空则用默认推断)"})
|
||||
return
|
||||
if "interval" in data:
|
||||
if not valid_interval(data.get("interval")):
|
||||
self._json({"ok": False, "msg": f"同步间隔须为 {MIN_INTERVAL} ~ {MAX_INTERVAL} 之间的整数(秒)"})
|
||||
@@ -1802,6 +1835,8 @@ class Handler(BaseHTTPRequestHandler):
|
||||
log("Gitea 密码已" + ("更新" if new_pass else "清除"))
|
||||
if new_host is not None:
|
||||
cfg["gitea_host"] = new_host
|
||||
if "open_url" in data:
|
||||
cfg["open_url"] = (data.get("open_url") or "").strip()
|
||||
if "auto_create" in data:
|
||||
cfg["auto_create"] = bool(data.get("auto_create"))
|
||||
if "interval" in data:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
appname = GiteaHubSync
|
||||
version = 1.5.5
|
||||
version = 1.5.6
|
||||
display_name = Gitea→GitHub 同步助手
|
||||
desc = 每次推送到飞牛 Gitea 的代码,10 秒内自动镜像到 GitHub 的 7 个私有仓库。内置控制面板:自动同步开关、立即同步、仓库状态、同步日志,一键打开 Gitea。数据全部保存在 NAS 本地。
|
||||
platform = all
|
||||
|
||||
Reference in New Issue
Block a user