根因:gitea_ui() 有个判断 bug——当请求 Host 是 127.0.0.1:8899 (CGI 内部连接面板的本地地址)时,面板把它当作"远程主机名" 去替换 gitea_host 中的 127.0.0.1,结果还是 127.0.0.1:3000。 修复: 1. 修判断 bug:只有推断出的真实主机名不是 loopback 时才替换 gitea_host 中的 127.0.0.1(本地直连保持原样,不再被错误"替换") 2. gitea_ui 新增 Referer 兜底:即使 CGI 没转发 Host/X-Forwarded-Host (fnOS CGI 环境里 $HTTP_HOST 可能为空),也能从浏览器自带的 Referer 头里推断出真实主机名 3. CGI 代理兜底转发:从 X-Forwarded-Host / HTTP_HOST / Referer 多源提取真实主机,作为 Host 和 X-Forwarded-Host 转发 4. 调用方传入 X-Forwarded-Host / Host / Referer 三个头 实测 6 种场景(远程 CGI / 远程直连 / 只有 Referer / 本地直连 / 全部为空 / 远程 IP)全部生成正确地址 manifest 1.5.4 → 1.5.5
78 lines
2.9 KiB
Bash
78 lines
2.9 KiB
Bash
#!/bin/bash
|
|
# GiteaHubSync CGI 入口:把控制面板(127.0.0.1:8899)代理到飞牛同源路径下,
|
|
# 使桌面图标 iframe 可以直接打开面板(避免 http/https 混合内容问题)。
|
|
# 完整转发 HTTP 方法、Content-Type 与请求体(POST /api/toggle、/api/sync 等)。
|
|
PANEL="http://127.0.0.1:8899"
|
|
APP_SLUG="GiteaHubSync"
|
|
|
|
URI_NO_QUERY="${REQUEST_URI%%\?*}"
|
|
REL_PATH="/"
|
|
case "$URI_NO_QUERY" in
|
|
*index.cgi*) REL_PATH="${URI_NO_QUERY#*index.cgi}" ;;
|
|
esac
|
|
REL_PATH="${REL_PATH#/}"
|
|
[ -z "$REL_PATH" ] && REL_PATH="/"
|
|
case "$REL_PATH" in /*) ;; *) REL_PATH="/$REL_PATH" ;; esac
|
|
|
|
METHOD="${REQUEST_METHOD:-GET}"
|
|
CTYPE="${CONTENT_TYPE:-application/json}"
|
|
|
|
HDR="$(mktemp)"; BODY="$(mktemp)"; INBODY=""
|
|
CURL_ARGS=(-s -m 120 -X "$METHOD" -H "Content-Type: $CTYPE")
|
|
# 把真实访问 Host / 协议转发给面板,面板据此把「打开 Gitea」等远程可访问
|
|
# 链接的主机名从 127.0.0.1/localhost 替换成用户实际访问的主机名。
|
|
# 真实主机从 X-Forwarded-Host / HTTP_HOST / Referer 中兜底提取(fnOS CGI
|
|
# 环境里 HTTP_HOST 可能为空)。
|
|
REAL_HOST=""
|
|
[ -n "$HTTP_X_FORWARDED_HOST" ] && REAL_HOST="$HTTP_X_FORWARDED_HOST"
|
|
[ -z "$REAL_HOST" ] && [ -n "$HTTP_HOST" ] && REAL_HOST="$HTTP_HOST"
|
|
if [ -z "$REAL_HOST" ] && [ -n "$HTTP_REFERER" ]; then
|
|
REAL_HOST=$(printf '%s' "$HTTP_REFERER" | sed -nE 's|^https?://([^/:/?#]+).*|\1|p' | head -1)
|
|
fi
|
|
if [ -n "$REAL_HOST" ]; then
|
|
CURL_ARGS+=(-H "Host: $REAL_HOST" -H "X-Forwarded-Host: $REAL_HOST")
|
|
fi
|
|
if [ "${HTTPS:-off}" = "on" ]; then
|
|
CURL_ARGS+=(-H "X-Forwarded-Proto: https")
|
|
else
|
|
CURL_ARGS+=(-H "X-Forwarded-Proto: http")
|
|
fi
|
|
case "$METHOD" in
|
|
POST|PUT|PATCH)
|
|
CL="${CONTENT_LENGTH:-0}"
|
|
if [ "$CL" -gt 0 ] 2>/dev/null; then
|
|
INBODY="$(mktemp)"
|
|
head -c "$CL" > "$INBODY"
|
|
CURL_ARGS+=(--data-binary "@$INBODY")
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
curl "${CURL_ARGS[@]}" -D "$HDR" -o "$BODY" "${PANEL}${REL_PATH}"
|
|
rc=$?
|
|
[ -n "$INBODY" ] && rm -f "$INBODY"
|
|
if [ $rc -ne 0 ]; then
|
|
rm -f "$HDR" "$BODY"
|
|
printf 'Status: 503 Service Unavailable\r\n'
|
|
printf 'Content-Type: text/html; charset=utf-8\r\n\r\n'
|
|
printf '<html><body style="font-family:sans-serif;padding:40px"><h3>同步服务未运行</h3><p>请到飞牛 应用中心 → 已安装 → GiteaHubSync 中启动应用。</p></body></html>\n'
|
|
exit 0
|
|
fi
|
|
|
|
CTYPE_OUT="$(grep -i '^content-type:' "$HDR" | head -1 | cut -d' ' -f2 | tr -d '\r')"
|
|
[ -z "$CTYPE_OUT" ] && CTYPE_OUT="text/html; charset=utf-8"
|
|
printf 'Content-Type: %s\r\n' "$CTYPE_OUT"
|
|
printf 'Cache-Control: no-store\r\n'
|
|
printf '\r\n'
|
|
case "$CTYPE_OUT" in
|
|
text/html*)
|
|
# 注入 <base>,让页面里的相对路径 API 请求落在本 CGI 前缀下
|
|
sed "s|<head>|<head><base href=\"/cgi/ThirdParty/${APP_SLUG}/index.cgi/\">|" "$BODY"
|
|
;;
|
|
*)
|
|
cat "$BODY"
|
|
;;
|
|
esac
|
|
rm -f "$HDR" "$BODY"
|
|
exit 0
|