x-ui/web/html/xui/form/stream/stream_xhttp.html
2026-05-19 01:00:32 +02:00

231 lines
No EOL
14 KiB
HTML

{{define "form/streamXHTTP"}}
<a-form :colon="false" :label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }">
<a-form-item label='{{ i18n "host" }}'>
<a-input v-model.trim="inbound.stream.xhttp.host"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "path" }}'>
<a-input v-model.trim="inbound.stream.xhttp.path"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.mode" }}'>
<a-select v-model="inbound.stream.xhttp.mode" style="width: 50%"
:dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="key in MODE_OPTION" :value="key">[[ key ]]</a-select-option>
</a-select>
</a-form-item>
<a-form-item>
<template slot="label">
<a-tooltip>
<template slot="title">
<span>{{ i18n "pages.inbounds.stream.xhttp.extraSettingsDesc" }}</span>
</template>
{{ i18n "pages.inbounds.stream.xhttp.extraSettings" }}
<a-icon type="question-circle"></a-icon>
</a-tooltip>
</template>
<a-switch v-model="inbound.stream.xhttp.extraEnable"></a-switch>
</a-form-item>
<template v-if="inbound.stream.xhttp.extraEnable">
<a-form-item label='{{ i18n "pages.inbounds.stream.tcp.requestHeader" }}'>
<a-button icon="plus" size="small"
@click="inbound.stream.xhttp.extra.addHeader('', '')"></a-button>
</a-form-item>
<a-form-item :wrapper-col="{span:24}">
<a-input-group compact v-for="(header, index) in inbound.stream.xhttp.extra.headers">
<a-input style="width: 50%" v-model.trim="header.name"
placeholder='{{ i18n "pages.inbounds.stream.general.name"}}'
:class="header.name && header.name.toLowerCase() === 'host' ? 'has-error' : ''">
<template slot="addonBefore" style="margin: 0;">[[ index+1 ]]</template>
</a-input>
<a-input style="width: 50%" v-model.trim="header.value"
placeholder='{{ i18n "pages.inbounds.stream.general.value" }}'>
<a-button slot="addonAfter" size="small"
@click="inbound.stream.xhttp.extra.removeHeader(index)">-</a-button>
</a-input>
</a-input-group>
<a-alert v-if="inbound.stream.xhttp.extra.headers.some(h => h.name && h.name.toLowerCase() === 'host')"
type="warning" show-icon style="margin-top: 4px;"
message='{{ i18n "pages.inbounds.stream.xhttp.hostHeaderForbidden" }}'>
</a-alert>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.maxBufferedUpload" }}'
v-if="inbound.stream.xhttp.mode === 'packet-up'">
<a-input-number v-model.number="inbound.stream.xhttp.extra.scMaxBufferedPosts"></a-input-number>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.maxUploadSize" }}'
v-if="inbound.stream.xhttp.mode === 'packet-up'">
<a-input v-model.trim="inbound.stream.xhttp.extra.scMaxEachPostBytes"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.streamUpServer" }}'
v-if="inbound.stream.xhttp.mode === 'stream-up'">
<a-input v-model.trim="inbound.stream.xhttp.extra.scStreamUpServerSecs"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.paddingBytes" }}'>
<a-input v-model.trim="inbound.stream.xhttp.extra.xPaddingBytes"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.paddingObfsMode" }}'>
<a-switch v-model="inbound.stream.xhttp.extra.xPaddingObfsMode"></a-switch>
</a-form-item>
<template v-if="inbound.stream.xhttp.extra.xPaddingObfsMode">
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.paddingKey" }}'>
<a-input v-model.trim="inbound.stream.xhttp.extra.xPaddingKey"
placeholder="x_padding"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.paddingHeader" }}'>
<a-input v-model.trim="inbound.stream.xhttp.extra.xPaddingHeader"
placeholder="X-Padding"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.paddingPlacement" }}'>
<a-select v-model="inbound.stream.xhttp.extra.xPaddingPlacement"
:dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option value>Default (queryInHeader)</a-select-option>
<a-select-option
value="queryInHeader">queryInHeader</a-select-option>
<a-select-option value="header">header</a-select-option>
</a-select>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.paddingMethod" }}'>
<a-select v-model="inbound.stream.xhttp.extra.xPaddingMethod"
:dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option value>Default (repeat-x)</a-select-option>
<a-select-option value="repeat-x">repeat-x</a-select-option>
<a-select-option value="tokenish">tokenish</a-select-option>
</a-select>
</a-form-item>
</template>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.uplinkHTTPMethod" }}'>
<a-select v-model="inbound.stream.xhttp.extra.uplinkHTTPMethod"
:dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option value>Default (POST)</a-select-option>
<a-select-option value="POST">POST</a-select-option>
<a-select-option value="PUT">PUT</a-select-option>
<a-select-option value="GET">GET (packet-up only)</a-select-option>
</a-select>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.sessionPlacement" }}'>
<a-select v-model="inbound.stream.xhttp.extra.sessionPlacement"
:dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option value>Default (path)</a-select-option>
<a-select-option value="path">path</a-select-option>
<a-select-option value="header">header</a-select-option>
<a-select-option value="cookie">cookie</a-select-option>
<a-select-option value="query">query</a-select-option>
</a-select>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.sessionKey" }}'
v-if="inbound.stream.xhttp.extra.sessionPlacement && inbound.stream.xhttp.extra.sessionPlacement !== 'path'">
<a-input v-model.trim="inbound.stream.xhttp.extra.sessionKey"
placeholder="x_session"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.seqPlacement" }}'>
<a-select v-model="inbound.stream.xhttp.extra.seqPlacement"
:dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option value>Default (path)</a-select-option>
<a-select-option value="path">path</a-select-option>
<a-select-option value="header">header</a-select-option>
<a-select-option value="cookie">cookie</a-select-option>
<a-select-option value="query">query</a-select-option>
</a-select>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.seqKey" }}'
v-if="inbound.stream.xhttp.extra.seqPlacement && inbound.stream.xhttp.extra.seqPlacement !== 'path'">
<a-input v-model.trim="inbound.stream.xhttp.extra.seqKey"
placeholder="x_seq"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.uplinkDataPlacement" }}'
v-if="inbound.stream.xhttp.mode === 'packet-up'">
<a-select v-model="inbound.stream.xhttp.extra.uplinkDataPlacement"
:dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option value>Default (body)</a-select-option>
<a-select-option value="body">body</a-select-option>
<a-select-option value="header">header</a-select-option>
<a-select-option value="query">query</a-select-option>
</a-select>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.uplinkDataKey" }}'
v-if="inbound.stream.xhttp.mode === 'packet-up' && inbound.stream.xhttp.extra.uplinkDataPlacement && inbound.stream.xhttp.extra.uplinkDataPlacement !== 'body'">
<a-input v-model.trim="inbound.stream.xhttp.extra.uplinkDataKey"
placeholder="x_data"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.uplinkChunkSize" }}'
v-if="inbound.stream.xhttp.mode === 'packet-up' && inbound.stream.xhttp.extra.uplinkDataPlacement && inbound.stream.xhttp.extra.uplinkDataPlacement !== 'body'">
<a-input-number v-model.number="inbound.stream.xhttp.extra.uplinkChunkSize"
:min="0" :placeholder='`0 ({{ i18n "unlimited" }})`'></a-input-number>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.noSSEHeader" }}'>
<a-switch v-model="inbound.stream.xhttp.extra.noSSEHeader"></a-switch>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.serverMaxHeaderBytes" }}'>
<a-tooltip placement="bottom">
<template slot="title">
<span>{{ i18n "pages.inbounds.stream.xhttp.serverMaxHeaderBytesDesc" }}</span>
</template>
<a-input-number v-model.number="inbound.stream.xhttp.extra.serverMaxHeaderBytes"
:min="0" placeholder="0 (=8192)"></a-input-number>
</a-tooltip>
</a-form-item>
<a-divider style="margin: 8px 0;">
<span style="font-size: 12px; opacity: 0.7;">{{ i18n "pages.inbounds.stream.xhttp.clientDefaults" }}</span>
</a-divider>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.noGRPCHeader" }}'
v-if="inbound.stream.xhttp.mode === 'stream-up' || inbound.stream.xhttp.mode === 'stream-one' || inbound.stream.xhttp.mode === 'auto'">
<a-tooltip placement="bottom">
<template slot="title">
<span>{{ i18n "pages.inbounds.stream.xhttp.noGRPCHeaderDesc" }}</span>
</template>
<a-switch v-model="inbound.stream.xhttp.extra.noGRPCHeader"></a-switch>
</a-tooltip>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.minUploadInterval" }}'
v-if="inbound.stream.xhttp.mode === 'packet-up' || inbound.stream.xhttp.mode === 'auto'">
<a-input v-model.trim="inbound.stream.xhttp.extra.scMinPostsIntervalMs"
placeholder="30 or 10-50 (range)"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.maxConcurrency" }}'
v-if="!inbound.stream.xhttp.extra.xmux.maxConnections">
<a-input v-model="inbound.stream.xhttp.extra.xmux.maxConcurrency" placeholder="16-32"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.maxConnections" }}'
v-if="!inbound.stream.xhttp.extra.xmux.maxConcurrency">
<a-input v-model="inbound.stream.xhttp.extra.xmux.maxConnections" :placeholder='`0 ({{ i18n "unlimited" }})`'></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.maxReuseTimes" }}'>
<a-input v-model="inbound.stream.xhttp.extra.xmux.cMaxReuseTimes"
:placeholder='`0 ({{ i18n "unlimited" }})`'></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.maxRequestTimes" }}'>
<a-input v-model="inbound.stream.xhttp.extra.xmux.hMaxRequestTimes"
placeholder="600-900"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.maxReusableSecs" }}'>
<a-input v-model="inbound.stream.xhttp.extra.xmux.hMaxReusableSecs"
placeholder="1800-3000"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.keepAlivePeriod" }}'>
<a-input-number v-model.number="inbound.stream.xhttp.extra.xmux.hKeepAlivePeriod"
placeholder="0 (auto)"></a-input-number>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.stream.xhttp.downloadSettings" }}'>
<a-tooltip placement="bottom">
<template slot="title">
<span>{{ i18n "pages.inbounds.stream.xhttp.downloadSettingsDesc" }}</span>
</template>
<a-switch v-model="inbound.stream.xhttp.extra.downloadSettingsEnable"></a-switch>
</a-tooltip>
</a-form-item>
<a-form-item v-if="inbound.stream.xhttp.extra.downloadSettingsEnable"
label='{{ i18n "pages.inbounds.stream.xhttp.downloadJSON" }}'
:wrapper-col="{ md: { span: 22 } }" :label-col="{ md: { span: 24 } }">
<a-input
type="textarea"
:auto-size="{ minRows: 8, maxRows: 20 }"
v-model="inbound.stream.xhttp.extra.downloadSettings"
style="font-family: monospace; direction: ltr; text-align: left;"
placeholder='{"address": "another.example.com", "port": 443, "network": "xhttp", "security": "tls", "tlsSettings": {}, "xhttpSettings": {"path": "/yourpath", "mode": "auto"}}'>
</a-input>
</a-form-item>
</template>
</a-form>
{{end}}