精简: 订阅极简输出: 去掉分流规则注入(Happ/Clash/Incy 远程规则源+remote_routing 拉取缓存+RemoteRoutingJob、Clash 远程规则合并簇、subJsonRules 注入); 保留多格式转换与默认极简模板

This commit is contained in:
Muse
2026-10-20 10:17:27 +00:00
parent 3cbf9164a4
commit 7d42b91ed6
25 changed files with 87 additions and 2100 deletions
+18 -18
View File
@@ -37,7 +37,7 @@ func outboundSettings(t *testing.T, raw []byte) map[string]any {
func TestSubJsonServiceInjectsGlobalFinalMask(t *testing.T) {
finalMask := `{"tcp":[{"type":"fragment","settings":{"packets":"tlshello","length":"100-200","delay":"10-20"}}],"udp":[{"type":"noise","settings":{"noise":[{"type":"base64","packet":"SGVsbG8="}]}}],"quicParams":{"congestion":"bbr"}}`
svc := NewSubJsonService("", "", finalMask, nil)
svc := NewSubJsonService("", finalMask, nil)
if hasDirectOutOutbound(svc) {
t.Fatal("direct_out outbound must never be emitted")
@@ -74,7 +74,7 @@ func TestSubJsonServiceInjectsGlobalFinalMask(t *testing.T) {
func TestSubJsonServiceMergesWithExistingFinalMask(t *testing.T) {
finalMask := `{"tcp":[{"type":"fragment","settings":{"packets":"tlshello"}}]}`
svc := NewSubJsonService("", "", finalMask, nil)
svc := NewSubJsonService("", finalMask, nil)
stream := svc.streamData(`{
"network":"tcp","security":"none","tcpSettings":{"header":{"type":"none"}},
@@ -94,7 +94,7 @@ func TestSubJsonServiceMergesWithExistingFinalMask(t *testing.T) {
}
func TestSubJsonServiceNoFinalMaskWhenEmpty(t *testing.T) {
svc := NewSubJsonService("", "", "", nil)
svc := NewSubJsonService("", "", nil)
stream := svc.streamData(`{"network":"tcp","security":"none","tcpSettings":{"header":{"type":"none"}}}`, "")
if _, ok := stream["finalmask"]; ok {
t.Fatal("no finalmask should be emitted when subJsonFinalMask is empty")
@@ -108,7 +108,7 @@ func TestSubJsonServiceNoFinalMaskWhenEmpty(t *testing.T) {
// the JSON subscription must emit that form, not an array, or v2ray clients fail
// to import the config (#5401).
func TestSubJsonServicePinnedCertJoinedToString(t *testing.T) {
svc := NewSubJsonService("", "", "", nil)
svc := NewSubJsonService("", "", nil)
stream := svc.streamData(`{"network":"tcp","security":"tls","tlsSettings":{"serverName":"a.example.com","settings":{"pinnedPeerCertSha256":["aa11","bb22"]}}}`, "")
tls, _ := stream["tlsSettings"].(map[string]any)
@@ -121,7 +121,7 @@ func TestSubJsonServicePinnedCertJoinedToString(t *testing.T) {
}
func TestSubJsonServiceTLSCipherSuitesForwarded(t *testing.T) {
svc := NewSubJsonService("", "", "", nil)
svc := NewSubJsonService("", "", nil)
stream := svc.streamData(`{"network":"tcp","security":"tls","tlsSettings":{"serverName":"a.example.com","cipherSuites":"TLS_AES_256_GCM_SHA384","settings":{}}}`, "")
tls, _ := stream["tlsSettings"].(map[string]any)
@@ -140,7 +140,7 @@ func TestSubJsonServiceVlessFlattened(t *testing.T) {
inbound := &model.Inbound{Listen: "1.2.3.4", Port: 443, Protocol: model.VLESS, Settings: `{"encryption":"none"}`}
client := model.Client{ID: "uuid-1", Flow: "xtls-rprx-vision"}
settings := outboundSettings(t, NewSubJsonService("", "", "", nil).genVless(&SubService{}, inbound, nil, client, ""))
settings := outboundSettings(t, NewSubJsonService("", "", nil).genVless(&SubService{}, inbound, nil, client, ""))
if _, ok := settings["vnext"]; ok {
t.Fatal("vless outbound must not use vnext")
}
@@ -153,7 +153,7 @@ func TestSubJsonServiceVlessFlowSuppressedByDisableFlow(t *testing.T) {
inbound := &model.Inbound{Listen: "1.2.3.4", Port: 443, Protocol: model.VLESS, Settings: `{"encryption":"none"}`, DisableFlow: true}
client := model.Client{ID: "uuid-1", Flow: "xtls-rprx-vision"}
settings := outboundSettings(t, NewSubJsonService("", "", "", nil).genVless(&SubService{}, inbound, nil, client, ""))
settings := outboundSettings(t, NewSubJsonService("", "", nil).genVless(&SubService{}, inbound, nil, client, ""))
if _, ok := settings["flow"]; ok {
t.Fatalf("DisableFlow inbound must not carry a flow in the JSON outbound: %#v", settings)
}
@@ -163,7 +163,7 @@ func TestSubJsonServiceVmessFlattened(t *testing.T) {
inbound := &model.Inbound{Listen: "1.2.3.4", Port: 443, Protocol: model.VMESS, Settings: `{}`}
client := model.Client{ID: "uuid-2"}
settings := outboundSettings(t, NewSubJsonService("", "", "", nil).genVnext(inbound, nil, client, ""))
settings := outboundSettings(t, NewSubJsonService("", "", nil).genVnext(inbound, nil, client, ""))
if _, ok := settings["vnext"]; ok {
t.Fatal("vmess outbound must not use vnext")
}
@@ -179,7 +179,7 @@ func TestSubJsonServiceServerUsesServersArray(t *testing.T) {
trojan := &model.Inbound{Listen: "1.2.3.4", Port: 443, Protocol: model.Trojan, Settings: `{}`}
client := model.Client{Password: "p4ss"}
settings := outboundSettings(t, NewSubJsonService("", "", "", nil).genServer(&SubService{}, trojan, nil, client, ""))
settings := outboundSettings(t, NewSubJsonService("", "", nil).genServer(&SubService{}, trojan, nil, client, ""))
server := firstServer(settings)
if server == nil {
t.Fatalf("trojan outbound must use a servers array, got: %#v", settings)
@@ -192,7 +192,7 @@ func TestSubJsonServiceServerUsesServersArray(t *testing.T) {
}
ss := &model.Inbound{Listen: "1.2.3.4", Port: 443, Protocol: model.Shadowsocks, Settings: `{"method":"aes-256-gcm"}`}
ssSettings := outboundSettings(t, NewSubJsonService("", "", "", nil).genServer(&SubService{}, ss, nil, client, ""))
ssSettings := outboundSettings(t, NewSubJsonService("", "", nil).genServer(&SubService{}, ss, nil, client, ""))
ssServer := firstServer(ssSettings)
if ssServer == nil {
t.Fatalf("shadowsocks outbound must use a servers array, got: %#v", ssSettings)
@@ -204,7 +204,7 @@ func TestSubJsonServiceServerUsesServersArray(t *testing.T) {
func TestSubJsonServiceXmuxSuppressesGlobalMux(t *testing.T) {
globalMux := `{"enabled":true,"concurrency":8}`
svc := NewSubJsonService(globalMux, "", "", nil)
svc := NewSubJsonService(globalMux, "", nil)
// When xmux is present in xhttpSettings, the per-inbound xmux handles
// multiplexing and the legacy outbound.Mux must NOT be set.
@@ -251,7 +251,7 @@ func TestSubJsonServiceXmuxSuppressesGlobalMux(t *testing.T) {
func TestSubJsonServiceGlobalMuxWhenNoXmux(t *testing.T) {
globalMux := `{"enabled":true,"concurrency":8}`
svc := NewSubJsonService(globalMux, "", "", nil)
svc := NewSubJsonService(globalMux, "", nil)
// When no xmux is present, the global subJsonMux should be used.
stream := `{"network":"xhttp","security":"tls","tlsSettings":{"serverName":"example.com"},"xhttpSettings":{"path":"/api","mode":"packet-up"}}`
@@ -305,7 +305,7 @@ func realitySpiderXFromStream(t *testing.T, svc *SubJsonService, clientKey strin
}
func TestSubJsonServiceRealityDataDerivesPerClientSpiderX(t *testing.T) {
svc := NewSubJsonService("", "", "", nil)
svc := NewSubJsonService("", "", nil)
alice := realitySpiderXFromStream(t, svc, "subAlice")
if again := realitySpiderXFromStream(t, svc, "subAlice"); again != alice {
@@ -321,13 +321,13 @@ func TestSubJsonServiceRealityDataDerivesPerClientSpiderX(t *testing.T) {
// security whose settings key is missing or null previously panicked the
// subscription request.
func TestSubJsonServiceStreamDataMalformedInputs(t *testing.T) {
withMask := NewSubJsonService("", "", `{"tcp":[{"type":"fragment"}]}`, nil)
withMask := NewSubJsonService("", `{"tcp":[{"type":"fragment"}]}`, nil)
stream := withMask.streamData("not-json", "clientKey")
if _, ok := stream["finalmask"]; !ok {
t.Fatal("finalMask must still apply when stream settings fail to parse")
}
svc := NewSubJsonService("", "", "", nil)
svc := NewSubJsonService("", "", nil)
noReality := svc.streamData(`{"network":"tcp","security":"reality"}`, "clientKey")
if v, ok := noReality["realitySettings"]; ok {
t.Fatalf("missing realitySettings must stay absent, got %v", v)
@@ -339,7 +339,7 @@ func TestSubJsonServiceStreamDataMalformedInputs(t *testing.T) {
}
func TestSubJsonServiceRealityDataSpiderXFallsBackWhenNoClientKey(t *testing.T) {
svc := NewSubJsonService("", "", "", nil)
svc := NewSubJsonService("", "", nil)
stream := svc.streamData(`{
"network":"tcp","security":"reality","tcpSettings":{"header":{"type":"none"}},
@@ -384,7 +384,7 @@ func TestSubJsonServiceWireguard(t *testing.T) {
AllowedIPs: []string{"10.0.0.2/32", "fd00::2/128"},
}
raw := NewSubJsonService("", "", "", nil).genWireguard(inbound, client)
raw := NewSubJsonService("", "", nil).genWireguard(inbound, client)
if raw == nil {
t.Fatal("genWireguard returned nil for a valid wireguard client")
}
@@ -428,7 +428,7 @@ func TestSubJsonServiceWireguardNoKey(t *testing.T) {
inbound := &model.Inbound{Listen: "203.0.113.9", Port: 51820, Protocol: model.WireGuard, Settings: `{}`}
client := model.Client{Email: "user"}
if raw := NewSubJsonService("", "", "", nil).genWireguard(inbound, client); raw != nil {
if raw := NewSubJsonService("", "", nil).genWireguard(inbound, client); raw != nil {
t.Fatalf("genWireguard = %s, want nil for a keyless wireguard client", raw)
}
}