feat(gateway): 一体化统一入口——路由与 Dashy 导航同一份数据、内置登录、原自定义错误页
目标:一个 HomeDash 容器取代 navi + portal-nginx + portal-auth。 - Route 扩展为"反代 + 导航"一条记录:kind(proxy/portal/auth)、streaming、 insecureTls、bypassPaths、injectBeian,以及 navEnabled/navSection/navName/ navDescription/navUrl/navIcon/navAutoIcon - 保存路由时**同时**写 gateway.yml 与 conf.yml 的导航项(gateway_nav.go): 同 host 接管而不是重复、未勾选导航的会被清理、无关手工项与系统「历史访问」分组 一律不动;两步任一步失败都回滚(避免后台显示与导航页各说各话) - 未知域名与上游故障改用**内置自定义 404/500 页面**(portal/ 目录), 不再是一行纯文本;HTTP→HTTPS 跳转段用 RedirectPort 复刻原 3081 设计 - 内置统一登录(auth.go):HMAC 签名 cookie、恒定时间比较、登录跳转白名单校验, portal-auth 容器可以退场 - 自动抓图标对托管导航项同样生效(history-server 识别 naviGatewayAutoIcon) - 后台卡片补齐"加入导航/分组/名称/描述/图标/自动抓图标/服务类型"字段 - 内部入口端口 8080 → 18080:为一体化 host 模式让开宿主机 blog(:8080) - 修掉上一轮编辑写坏的 deploy/zd.sh 一行(会让脚本直接失败) 测试:新增自定义错误页、portal 类型、导航字段校验、导航同步(接管/清理/保留)、 分组不存在必须报错等用例;admin-server 与 history-server 全绿。
This commit is contained in:
@ -1053,11 +1053,38 @@ func handleGatewayRoutes(w http.ResponseWriter, r *http.Request) {
|
||||
if req.ListenTLSPort == 0 {
|
||||
req.ListenTLSPort = 8443
|
||||
}
|
||||
// 路由与 Dashy 导航是一份操作:先确认导航分组都存在,再同时更新。
|
||||
// 任一步失败都恢复 gateway.yml 与 conf.yml,避免后台显示和导航页各说各话。
|
||||
dashy, err := loadConfig()
|
||||
if err != nil {
|
||||
jsonErr(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
if err := validateGatewayNavigation(&req, dashy); err != nil {
|
||||
jsonErr(w, 400, err.Error())
|
||||
return
|
||||
}
|
||||
oldGateway, gatewayExisted := os.ReadFile(gatewayFile)
|
||||
oldConf, confErr := os.ReadFile(confFile)
|
||||
if confErr != nil {
|
||||
jsonErr(w, 500, confErr.Error())
|
||||
return
|
||||
}
|
||||
if err := saveGateway(&req); err != nil {
|
||||
jsonErr(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResp(w, map[string]string{"status": "saved"})
|
||||
if err := syncGatewayNavigation(&req); err != nil {
|
||||
if gatewayExisted == nil {
|
||||
_ = os.WriteFile(gatewayFile, oldGateway, 0o600)
|
||||
} else {
|
||||
_ = os.Remove(gatewayFile)
|
||||
}
|
||||
_ = os.WriteFile(confFile, oldConf, 0o644)
|
||||
jsonErr(w, 500, "同步 Dashy 导航失败,已回滚:"+err.Error())
|
||||
return
|
||||
}
|
||||
jsonResp(w, map[string]any{"status": "saved", "routes": len(req.Routes)})
|
||||
default:
|
||||
jsonErr(w, 405, "method not allowed")
|
||||
}
|
||||
@ -1130,6 +1157,9 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
// 内置统一登录服务:与 gateway 共处一个容器,不再需要 portal-auth 容器。
|
||||
registerPortalAuth()
|
||||
|
||||
// Serve admin UI static files (nginx strips /admin/ prefix)
|
||||
http.Handle("/", http.FileServer(http.Dir("/app/admin")))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user