2026-05-25 21:13:29 +00:00
|
|
|
import { z } from 'zod';
|
|
|
|
|
|
|
|
|
|
import { WsHeaderMapSchema } from '@/schemas/protocols/stream/ws';
|
|
|
|
|
|
|
|
|
|
export const XHttpModeSchema = z.enum(['auto', 'packet-up', 'stream-up', 'stream-one']);
|
|
|
|
|
export type XHttpMode = z.infer<typeof XHttpModeSchema>;
|
|
|
|
|
|
|
|
|
|
// xHTTP (SplitHTTPConfig) is xray-core's modern stream-multiplexed transport.
|
|
|
|
|
// The field set is large because the schema mirrors what the server-side
|
|
|
|
|
// listener reads — plus a few client-only fields (`uplinkHTTPMethod`,
|
|
|
|
|
// `headers`) the panel embeds into share-link `extra` blobs even though the
|
|
|
|
|
// server ignores them at runtime. Outbound has additional fields (uplinkChunk
|
|
|
|
|
// sizes, noGRPCHeader, scMinPostsIntervalMs, xmux, downloadSettings) which
|
|
|
|
|
// belong on the outbound class instead, not modeled here.
|
feat(frontend): XHTTP advanced fields on outbound modal
Replace the 'edit via JSON' deferred-features hint with the full XHTTP
sub-form matching the legacy modal's XhttpFields helper.
schemas/protocols/stream/xhttp.ts:
- New XHttpXmuxSchema: 6 connection-multiplexing knobs
(maxConcurrency, maxConnections, cMaxReuseTimes, hMaxRequestTimes,
hMaxReusableSecs, hKeepAlivePeriod).
- XHttpStreamSettingsSchema gains 5 outbound-only fields and one
UI-only toggle: scMinPostsIntervalMs, uplinkChunkSize, noGRPCHeader,
xmux, enableXmux.
outbound-form-adapter.ts:
- New stripUiOnlyStreamFields() drops xhttpSettings.enableXmux on the
way to wire so the panel never embeds the UI toggle into the saved
config. xray-core ignores unknown fields anyway, but the panel reads
back its own emitted JSON, so a clean wire shape matters.
OutboundFormModal.tsx:
- Headers editor (HeaderMapEditor v1) for xhttpSettings.headers.
- Padding obfs Switch + 4 conditional fields (key/header/placement/
method) when on.
- Uplink HTTP method Select with GET disabled outside packet-up.
- Session placement + session key (key shown when placement != path).
- Sequence placement + sequence key (same pattern).
- packet-up mode: scMinPostsIntervalMs, scMaxEachPostBytes, uplink
data placement + key + chunk size (key/chunk-size shown when
placement != body).
- stream-up / stream-one mode: noGRPCHeader Switch.
- XMUX Switch + 6 nested fields when on.
2026-05-26 11:19:08 +00:00
|
|
|
// XMUX is the connection-multiplexing layer xHTTP uses to fan out
|
|
|
|
|
// parallel requests over a small pool of upstream connections. Fields
|
|
|
|
|
// are strings because they accept dash-range values like '16-32'.
|
|
|
|
|
export const XHttpXmuxSchema = z.object({
|
|
|
|
|
maxConcurrency: z.string().default('16-32'),
|
|
|
|
|
maxConnections: z.union([z.string(), z.number()]).default(0),
|
|
|
|
|
cMaxReuseTimes: z.union([z.string(), z.number()]).default(0),
|
|
|
|
|
hMaxRequestTimes: z.string().default('600-900'),
|
|
|
|
|
hMaxReusableSecs: z.string().default('1800-3000'),
|
|
|
|
|
hKeepAlivePeriod: z.number().int().min(0).default(0),
|
|
|
|
|
});
|
|
|
|
|
export type XHttpXmux = z.infer<typeof XHttpXmuxSchema>;
|
|
|
|
|
|
2026-05-25 21:13:29 +00:00
|
|
|
export const XHttpStreamSettingsSchema = z.object({
|
|
|
|
|
path: z.string().default('/'),
|
|
|
|
|
host: z.string().default(''),
|
|
|
|
|
mode: XHttpModeSchema.default('auto'),
|
|
|
|
|
xPaddingBytes: z.string().default('100-1000'),
|
|
|
|
|
xPaddingObfsMode: z.boolean().default(false),
|
|
|
|
|
xPaddingKey: z.string().default(''),
|
|
|
|
|
xPaddingHeader: z.string().default(''),
|
|
|
|
|
xPaddingPlacement: z.string().default(''),
|
|
|
|
|
xPaddingMethod: z.string().default(''),
|
|
|
|
|
sessionPlacement: z.string().default(''),
|
|
|
|
|
sessionKey: z.string().default(''),
|
|
|
|
|
seqPlacement: z.string().default(''),
|
|
|
|
|
seqKey: z.string().default(''),
|
|
|
|
|
uplinkDataPlacement: z.string().default(''),
|
|
|
|
|
uplinkDataKey: z.string().default(''),
|
|
|
|
|
scMaxEachPostBytes: z.string().default('1000000'),
|
|
|
|
|
noSSEHeader: z.boolean().default(false),
|
|
|
|
|
scMaxBufferedPosts: z.number().int().min(0).default(30),
|
|
|
|
|
scStreamUpServerSecs: z.string().default('20-80'),
|
|
|
|
|
serverMaxHeaderBytes: z.number().int().min(0).default(0),
|
|
|
|
|
uplinkHTTPMethod: z.string().default(''),
|
|
|
|
|
headers: WsHeaderMapSchema.default({}),
|
feat(frontend): XHTTP advanced fields on outbound modal
Replace the 'edit via JSON' deferred-features hint with the full XHTTP
sub-form matching the legacy modal's XhttpFields helper.
schemas/protocols/stream/xhttp.ts:
- New XHttpXmuxSchema: 6 connection-multiplexing knobs
(maxConcurrency, maxConnections, cMaxReuseTimes, hMaxRequestTimes,
hMaxReusableSecs, hKeepAlivePeriod).
- XHttpStreamSettingsSchema gains 5 outbound-only fields and one
UI-only toggle: scMinPostsIntervalMs, uplinkChunkSize, noGRPCHeader,
xmux, enableXmux.
outbound-form-adapter.ts:
- New stripUiOnlyStreamFields() drops xhttpSettings.enableXmux on the
way to wire so the panel never embeds the UI toggle into the saved
config. xray-core ignores unknown fields anyway, but the panel reads
back its own emitted JSON, so a clean wire shape matters.
OutboundFormModal.tsx:
- Headers editor (HeaderMapEditor v1) for xhttpSettings.headers.
- Padding obfs Switch + 4 conditional fields (key/header/placement/
method) when on.
- Uplink HTTP method Select with GET disabled outside packet-up.
- Session placement + session key (key shown when placement != path).
- Sequence placement + sequence key (same pattern).
- packet-up mode: scMinPostsIntervalMs, scMaxEachPostBytes, uplink
data placement + key + chunk size (key/chunk-size shown when
placement != body).
- stream-up / stream-one mode: noGRPCHeader Switch.
- XMUX Switch + 6 nested fields when on.
2026-05-26 11:19:08 +00:00
|
|
|
// Outbound-only fields. Server (inbound) listener ignores these. The
|
|
|
|
|
// panel embeds them in share-link `extra` blobs so the same xhttp
|
|
|
|
|
// config can roundtrip on both sides.
|
|
|
|
|
scMinPostsIntervalMs: z.string().default('30'),
|
|
|
|
|
uplinkChunkSize: z.number().int().min(0).default(0),
|
|
|
|
|
noGRPCHeader: z.boolean().default(false),
|
|
|
|
|
xmux: XHttpXmuxSchema.optional(),
|
|
|
|
|
// UI-only toggle controlling whether the XMUX sub-form is expanded.
|
|
|
|
|
// Never present on the wire — outbound modal strips it via the
|
|
|
|
|
// form-to-wire adapter.
|
|
|
|
|
enableXmux: z.boolean().default(false),
|
2026-05-25 21:13:29 +00:00
|
|
|
});
|
|
|
|
|
export type XHttpStreamSettings = z.infer<typeof XHttpStreamSettingsSchema>;
|