feat(routing): connect 读 per-user 档案传入渲染(fail-safe 回退默认)
This commit is contained in:
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/wangjia/pangolin/server/internal/auth"
|
||||
"github.com/wangjia/pangolin/server/internal/nodes"
|
||||
agentv1 "github.com/wangjia/pangolin/server/internal/pb/agentv1"
|
||||
"github.com/wangjia/pangolin/server/internal/routing"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -45,13 +46,17 @@ type NodeAPI struct {
|
||||
// privateSplitDomains 私有服务域名(PANGOLIN_PRIVATE_SPLIT_DOMAINS,逗号分隔),
|
||||
// 见 ClientConfigOpts.PrivateSplitDomains;空则不渲染相关规则。
|
||||
privateSplitDomains []string
|
||||
// routingStore 读取用户可配置分流档案(Task 1)。nil = 未注入(旧路径/未迁移
|
||||
// 调用点),ConnectNode 回退到 ?split_cn query 兜底,不产坏配置。
|
||||
routingStore *routing.Store
|
||||
}
|
||||
|
||||
// NewNodeAPI creates a NodeAPI. load may be nil (then all nodes are treated as
|
||||
// data-plane healthy — agent gRPC liveness still gates status).
|
||||
func NewNodeAPI(store nodes.NodeStore, hub *nodes.Hub, load nodeLoadReader, deriveKey, rulesBaseURL string, privateSplitDomains []string) *NodeAPI {
|
||||
// data-plane healthy — agent gRPC liveness still gates status). routingStore
|
||||
// may be nil (per-user 路由档案不生效,ConnectNode 回退到 ?split_cn query)。
|
||||
func NewNodeAPI(store nodes.NodeStore, hub *nodes.Hub, load nodeLoadReader, deriveKey, rulesBaseURL string, privateSplitDomains []string, routingStore *routing.Store) *NodeAPI {
|
||||
return &NodeAPI{store: store, hub: hub, load: load, deriveKey: deriveKey,
|
||||
rulesBaseURL: rulesBaseURL, privateSplitDomains: privateSplitDomains}
|
||||
rulesBaseURL: rulesBaseURL, privateSplitDomains: privateSplitDomains, routingStore: routingStore}
|
||||
}
|
||||
|
||||
// dataPlaneHealthy reports the node's last sing-box health (default true when
|
||||
@@ -316,10 +321,23 @@ func (a *NodeAPI) ConnectNode(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// 7. Render and return the full sing-box CLIENT config JSON.
|
||||
// split_cn=1/true → 国内 IP/域名直连(#5);客户端按 smartRoute 偏好传。
|
||||
// 可配置分流(Phase 1):读取用户路由档案,读取/解析失败一律回退 prof=nil
|
||||
// (fail-safe,不产坏配置)。有档案时国内分流开关由档案决定;无档案(未迁移
|
||||
// 用户/store 未注入)保留 ?split_cn query 兜底旧行为。
|
||||
var prof *routing.Profile
|
||||
if a.routingStore != nil {
|
||||
if p, perr := a.routingStore.Get(r.Context(), uid); perr == nil {
|
||||
prof = p
|
||||
} else {
|
||||
slog.Warn("connect: routing profile load failed, falling back to default", "user", uid, "err", perr)
|
||||
}
|
||||
}
|
||||
splitCN := r.URL.Query().Get("split_cn") == "1" || r.URL.Query().Get("split_cn") == "true"
|
||||
if prof != nil {
|
||||
splitCN = prof.Mode == "rule" && prof.Builtin.ChinaDirect
|
||||
}
|
||||
cfgJSON, renderErr := BuildClientConfig(node, dpUUID, a.deriveKey,
|
||||
ClientConfigOpts{SplitCN: splitCN, RulesBaseURL: a.rulesBaseURL,
|
||||
ClientConfigOpts{Profile: prof, SplitCN: splitCN, RulesBaseURL: a.rulesBaseURL,
|
||||
PrivateSplitDomains: a.privateSplitDomains})
|
||||
if renderErr != nil {
|
||||
slog.Error("connect: build client config failed", "node", nodeUUID, "err", renderErr)
|
||||
|
||||
Reference in New Issue
Block a user