mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-28 00:24:19 +00:00
feat(xhttp): support sessionID* rename + sessionIDTable/Length (xray v26.6.22) (#5506)
* feat(xhttp): support sessionID* rename + sessionIDTable/Length (xray v26.6.22) xray-core v26.6.22 (PR #6258) renamed the XHTTP session config keys sessionPlacement/sessionKey to sessionIDPlacement/sessionIDKey (no fallback kept in core) and added sessionIDTable (predefined charset name or literal ASCII) and sessionIDLength (range, e.g. 16-32, lower bound > 0). Panel changes: - Schema (xhttp.ts): rename the two keys, add sessionIDTable/sessionIDLength, and a z.preprocess that lifts legacy keys off stored configs so an upgraded panel never silently drops a saved session setting. - Wire normalize + share-link build/parse: rename keys, emit the two new fields, and accept legacy sessionPlacement/sessionKey from old share links. - Inbound + outbound XHTTP forms: rename field paths, add a sessionIDTable autocomplete (9 predefined tables + free ASCII) and a sessionIDLength range input shown only when a table is set, with light client validation (ASCII table, length min > 0; xray enforces the room-size minimum server-side). - Subscription (service.go) and Clash (clash_service.go) builders: emit the renamed + new keys, with a legacy fallback for not-yet-resaved inbounds. - Locales: add sessionIDTable/sessionIDLength labels + hints in all 13 files. Two sibling v26.6.22 XHTTP commits need no panel change and are covered by the core bump alone: #6332 (XHTTP/3 closes QUIC/UDP) and #6320 (udpHop honors the existing dialerProxy). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(xhttp): add Session ID Table to inbound form-blocks snapshot The new sessionIDTable input renders by default in the inbound XHTTP form, so its label joins the field-structure snapshot. sessionIDLength stays conditional (only shown when a table is set), so it does not appear here. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(xhttp): migrate legacy session keys in the running xray config The Zod preprocess plus the subscription/Clash fallbacks only covered the panel UI and share-link output. The config handed to the running xray-core process is built from the raw stored streamSettings in GetXrayConfig, which did not rewrite the renamed XHTTP session keys — so a pre-upgrade inbound (or template outbound) stored with a non-default sessionPlacement was emitted unchanged and dropped by xray-core v26.6.22, until the admin re-saved it. Lift sessionPlacement/sessionKey onto sessionIDPlacement/sessionIDKey at config-generation time, in the existing inbound stream-rewrite block (next to the tls/reality/externalProxy handling) and across template outbounds. The lift is idempotent and leaves unchanged configs byte-identical so the hot-reload diff never sees a spurious change. Also tighten validateSessionIDLength to reject an inverted range (e.g. 32-16) in addition to the existing lower-bound > 0 check. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(xray): avoid summed-capacity allocation in mergeSubscriptionOutbounds CodeQL go/allocation-size-overflow flagged the pre-sized make() whose capacity was a sum of three slice lengths. Grow the slice via append on a nil slice instead; same result, no overflow-prone capacity expression.
This commit is contained in:
@@ -404,8 +404,10 @@ func buildXhttpClashOpts(xhttp map[string]any) map[string]any {
|
||||
stringFields := []xhttpStringField{
|
||||
{"xPaddingBytes", "x-padding-bytes", ""},
|
||||
{"uplinkHTTPMethod", "uplink-http-method", ""},
|
||||
{"sessionPlacement", "session-placement", ""},
|
||||
{"sessionKey", "session-key", ""},
|
||||
{"sessionIDPlacement", "session-id-placement", ""},
|
||||
{"sessionIDKey", "session-id-key", ""},
|
||||
{"sessionIDTable", "session-id-table", ""},
|
||||
{"sessionIDLength", "session-id-length", ""},
|
||||
{"seqPlacement", "seq-placement", ""},
|
||||
{"seqKey", "seq-key", ""},
|
||||
{"uplinkDataPlacement", "uplink-data-placement", ""},
|
||||
@@ -420,6 +422,21 @@ func buildXhttpClashOpts(xhttp map[string]any) map[string]any {
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy inbounds (pre xray-core #6258) stored sessionPlacement/sessionKey.
|
||||
// Fall back to them so not-yet-resaved configs still map. Mirrors the
|
||||
// frontend migration.
|
||||
for _, f := range []xhttpStringField{
|
||||
{"sessionPlacement", "session-id-placement", ""},
|
||||
{"sessionKey", "session-id-key", ""},
|
||||
} {
|
||||
if _, exists := opts[f.dst]; exists {
|
||||
continue
|
||||
}
|
||||
if v, ok := xhttp[f.src].(string); ok && v != "" {
|
||||
opts[f.dst] = v
|
||||
}
|
||||
}
|
||||
|
||||
// Bool fields (truthy only)
|
||||
if v, ok := xhttp["noGRPCHeader"].(bool); ok && v {
|
||||
opts["no-grpc-header"] = true
|
||||
|
||||
@@ -330,8 +330,10 @@ func TestBuildXhttpClashOpts_FullFieldMapping(t *testing.T) {
|
||||
"xPaddingPlacement": "queryInHeader",
|
||||
"xPaddingMethod": "tokenish",
|
||||
"uplinkHTTPMethod": "POST",
|
||||
"sessionPlacement": "query",
|
||||
"sessionKey": "sess",
|
||||
"sessionIDPlacement": "query",
|
||||
"sessionIDKey": "sess",
|
||||
"sessionIDTable": "Base62",
|
||||
"sessionIDLength": "16-32",
|
||||
"seqPlacement": "header",
|
||||
"seqKey": "seq",
|
||||
"uplinkDataPlacement": "body",
|
||||
@@ -377,11 +379,17 @@ func TestBuildXhttpClashOpts_FullFieldMapping(t *testing.T) {
|
||||
if opts["uplink-http-method"] != "POST" {
|
||||
t.Errorf("uplink-http-method = %v", opts["uplink-http-method"])
|
||||
}
|
||||
if opts["session-placement"] != "query" {
|
||||
t.Errorf("session-placement = %v", opts["session-placement"])
|
||||
if opts["session-id-placement"] != "query" {
|
||||
t.Errorf("session-id-placement = %v", opts["session-id-placement"])
|
||||
}
|
||||
if opts["session-key"] != "sess" {
|
||||
t.Errorf("session-key = %v", opts["session-key"])
|
||||
if opts["session-id-key"] != "sess" {
|
||||
t.Errorf("session-id-key = %v", opts["session-id-key"])
|
||||
}
|
||||
if opts["session-id-table"] != "Base62" {
|
||||
t.Errorf("session-id-table = %v", opts["session-id-table"])
|
||||
}
|
||||
if opts["session-id-length"] != "16-32" {
|
||||
t.Errorf("session-id-length = %v", opts["session-id-length"])
|
||||
}
|
||||
if opts["seq-placement"] != "header" {
|
||||
t.Errorf("seq-placement = %v", opts["seq-placement"])
|
||||
|
||||
+15
-1
@@ -1731,7 +1731,7 @@ func buildXhttpExtra(xhttp map[string]any) map[string]any {
|
||||
|
||||
stringFields := []string{
|
||||
"uplinkHTTPMethod",
|
||||
"sessionPlacement", "sessionKey",
|
||||
"sessionIDPlacement", "sessionIDKey", "sessionIDTable", "sessionIDLength",
|
||||
"seqPlacement", "seqKey",
|
||||
"uplinkDataPlacement", "uplinkDataKey",
|
||||
"scMaxEachPostBytes", "scMinPostsIntervalMs",
|
||||
@@ -1750,6 +1750,20 @@ func buildXhttpExtra(xhttp map[string]any) map[string]any {
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy inbounds (pre xray-core #6258) stored sessionPlacement/sessionKey.
|
||||
// Lift them onto the renamed keys so links from not-yet-resaved configs
|
||||
// still carry the session settings. Mirrors the frontend migration.
|
||||
for legacy, renamed := range map[string]string{
|
||||
"sessionPlacement": "sessionIDPlacement",
|
||||
"sessionKey": "sessionIDKey",
|
||||
} {
|
||||
if _, exists := extra[renamed]; !exists {
|
||||
if v, ok := xhttp[legacy].(string); ok && len(v) > 0 {
|
||||
extra[renamed] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, field := range []string{"uplinkChunkSize"} {
|
||||
if v, ok := nonZeroShareValue(xhttp[field]); ok {
|
||||
extra[field] = v
|
||||
|
||||
Reference in New Issue
Block a user