mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-23 04:56:07 +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:
@@ -25,7 +25,34 @@ export const XHttpXmuxSchema = z.object({
|
||||
});
|
||||
export type XHttpXmux = z.infer<typeof XHttpXmuxSchema>;
|
||||
|
||||
export const XHttpStreamSettingsSchema = z.object({
|
||||
// Predefined sessionIDTable names xray-core accepts as a shorthand for a
|
||||
// charset (splithttp.PredefinedTable, xray-core #6258). A literal ASCII
|
||||
// charset string is also accepted.
|
||||
export const XHTTP_SESSION_ID_TABLES = [
|
||||
'ALPHABET', 'Alphabet', 'BASE36', 'Base62', 'HEX',
|
||||
'alphabet', 'base36', 'hex', 'number',
|
||||
] as const;
|
||||
|
||||
// xray-core #6258 renamed sessionPlacement/sessionKey to
|
||||
// sessionIDPlacement/sessionIDKey (no fallback kept in core) and added
|
||||
// sessionIDTable/sessionIDLength. Lift any legacy keys persisted by an older
|
||||
// panel onto the new names so a saved inbound/outbound never silently loses
|
||||
// its session setting, then drop the legacy keys so we never emit both.
|
||||
function migrateLegacyXhttp(v: unknown): unknown {
|
||||
if (v == null || typeof v !== 'object' || Array.isArray(v)) return v;
|
||||
const o = { ...(v as Record<string, unknown>) };
|
||||
if (o.sessionIDPlacement === undefined && o.sessionPlacement !== undefined) {
|
||||
o.sessionIDPlacement = o.sessionPlacement;
|
||||
}
|
||||
if (o.sessionIDKey === undefined && o.sessionKey !== undefined) {
|
||||
o.sessionIDKey = o.sessionKey;
|
||||
}
|
||||
delete o.sessionPlacement;
|
||||
delete o.sessionKey;
|
||||
return o;
|
||||
}
|
||||
|
||||
export const XHttpStreamSettingsSchema = z.preprocess(migrateLegacyXhttp, z.object({
|
||||
path: z.string().default('/'),
|
||||
host: z.string().default(''),
|
||||
mode: XHttpModeSchema.default('auto'),
|
||||
@@ -35,8 +62,13 @@ export const XHttpStreamSettingsSchema = z.object({
|
||||
xPaddingHeader: z.string().default(''),
|
||||
xPaddingPlacement: z.string().default(''),
|
||||
xPaddingMethod: z.string().default(''),
|
||||
sessionPlacement: z.string().default(''),
|
||||
sessionKey: z.string().default(''),
|
||||
sessionIDPlacement: z.string().default(''),
|
||||
sessionIDKey: z.string().default(''),
|
||||
// sessionIDTable: a predefined name (XHTTP_SESSION_ID_TABLES) or a literal
|
||||
// ASCII charset. sessionIDLength: dash-range string (e.g. '8-16'); only
|
||||
// honored when a table is set. xray-core enforces the room-size minimum.
|
||||
sessionIDTable: z.string().default(''),
|
||||
sessionIDLength: z.string().default(''),
|
||||
seqPlacement: z.string().default(''),
|
||||
seqKey: z.string().default(''),
|
||||
uplinkDataPlacement: z.string().default(''),
|
||||
@@ -65,5 +97,5 @@ export const XHttpStreamSettingsSchema = z.object({
|
||||
// Never present on the wire — outbound modal strips it via the
|
||||
// form-to-wire adapter.
|
||||
enableXmux: z.boolean().default(false),
|
||||
});
|
||||
}));
|
||||
export type XHttpStreamSettings = z.infer<typeof XHttpStreamSettingsSchema>;
|
||||
|
||||
Reference in New Issue
Block a user