mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-13 23:01:00 +00:00
feat(reality): derive a stable per-client spiderX for shared links
The inbound's spiderX now acts as a per-client seed: exports emit sha256(seed|subKey) truncated to a 15-hex "/path", so a client's spx no longer changes on every subscription fetch (#5718) while different clients stop sharing one fingerprintable value. The form gains a regenerate button that rotates every client's path at once. The frontend link builders derive through the same function (lib/xray/spider-x.ts, @noble/hashes) keyed on subId-then-email like the Go subKey, so panel QR/copy links and subscription output agree — cross-language vector tests lock both sides byte-for-byte. streamData now tolerates malformed stored stream settings (unparseable JSON, null tls/reality settings) instead of panicking the subscription request.
This commit is contained in:
@@ -95,15 +95,15 @@ func TestSubJsonService_MuxAttachedWhenConfigured(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// --- json_service.go:268 — a non-empty finalMask that merges to nothing must
|
||||
// --- applyGlobalFinalMask — a non-empty finalMask that merges to nothing must
|
||||
// not add the finalmask key (the `len(merged) > 0` guard). ---
|
||||
|
||||
func TestSubJsonService_FinalMaskMergingToEmptyNotAdded(t *testing.T) {
|
||||
// finalMask is non-empty (passes the len(fm)==0 early return) but its only
|
||||
// key is an empty tcp slice, which mergeFinalMask drops → merged is empty,
|
||||
// so applyGlobalFinalMask (json_service.go:268) must NOT set finalmask.
|
||||
// so applyGlobalFinalMask must NOT set finalmask.
|
||||
svc := NewSubJsonService("", "", `{"tcp":[]}`, nil)
|
||||
stream := svc.streamData(`{"network":"tcp","security":"none","tcpSettings":{"header":{"type":"none"}}}`)
|
||||
stream := svc.streamData(`{"network":"tcp","security":"none","tcpSettings":{"header":{"type":"none"}}}`, "")
|
||||
if _, ok := stream["finalmask"]; ok {
|
||||
t.Fatalf("finalMask merging to empty must not add a finalmask key: %#v", stream["finalmask"])
|
||||
}
|
||||
@@ -111,13 +111,13 @@ func TestSubJsonService_FinalMaskMergingToEmptyNotAdded(t *testing.T) {
|
||||
// Sanity: a finalMask that DOES merge to something still gets set, so the
|
||||
// guard is the only distinguishing factor.
|
||||
svc2 := NewSubJsonService("", "", `{"tcp":[{"type":"fragment"}]}`, nil)
|
||||
stream2 := svc2.streamData(`{"network":"tcp","security":"none","tcpSettings":{"header":{"type":"none"}}}`)
|
||||
stream2 := svc2.streamData(`{"network":"tcp","security":"none","tcpSettings":{"header":{"type":"none"}}}`, "")
|
||||
if _, ok := stream2["finalmask"]; !ok {
|
||||
t.Fatal("non-empty finalMask must be set")
|
||||
}
|
||||
}
|
||||
|
||||
// --- json_service.go:494 — an empty extra tcp slice must not clobber the base ---
|
||||
// --- mergeFinalMask — an empty extra tcp slice must not clobber the base ---
|
||||
|
||||
func TestMergeFinalMask_EmptyExtraTcpKeepsBase(t *testing.T) {
|
||||
base := map[string]any{"tcp": []any{map[string]any{"type": "keep"}}}
|
||||
|
||||
Reference in New Issue
Block a user