3 コミット 2982d809ab ... f497a8dbcc

作者 SHA1 メッセージ 日付
  mhsanaei f497a8dbcc v2.4.7 1 週間 前
  mhsanaei 4290081486 readme: postman 1 週間 前
  mhsanaei ccda652e69 SplitHTTP - Mode 1 週間 前

+ 2 - 2
README.es_ES.md

@@ -477,7 +477,7 @@ Ingresa el ID de chat de usuario en el campo de entrada número 4. Las cuentas d
 
 #### Uso
 
-- [Documentación de API](https://documenter.getpostman.com/view/5146551/2sAXxP8Y12)
+- [Documentación de API](https://www.postman.com/hsanaei/3x-ui/collection/q1l5l0u/3x-ui)
 - `/login` con `POST` datos de usuario: `{username: '', password: ''}` para iniciar sesión
 - `/panel/api/inbounds` base para las siguientes acciones:
 
@@ -507,7 +507,7 @@ Ingresa el ID de chat de usuario en el campo de entrada número 4. Las cuentas d
 - `client.password` para TROJAN
 - `client.email` para Shadowsocks
 
-- [<img src="https://run.pstmn.io/button.svg" alt="Run In Postman" style="width: 128px; height: 32px;">](https://god.gw.postman.com/run-collection/5146551-e6aac565-e0e2-46df-acff-2607a51bbd04?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-e6aac565-e0e2-46df-acff-2607a51bbd04%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124)
+- [<img src="https://run.pstmn.io/button.svg" alt="Run In Postman" style="width: 128px; height: 32px;">](https://app.getpostman.com/run-collection/5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124)
 </details>
 
 ## Variables de Entorno

+ 2 - 2
README.md

@@ -488,7 +488,7 @@ Enter the user ID in input field number 4. The Telegram accounts with this id wi
 
 #### Usage
 
-- [API Documentation](https://documenter.getpostman.com/view/5146551/2sAXxP8Y12)
+- [API Documentation](https://www.postman.com/hsanaei/3x-ui/collection/q1l5l0u/3x-ui)
 - `/login` with `POST` user data: `{username: '', password: ''}` for login
 - `/panel/api/inbounds` base for following actions:
 
@@ -519,7 +519,7 @@ Enter the user ID in input field number 4. The Telegram accounts with this id wi
 - `client.password` for TROJAN
 - `client.email` for Shadowsocks
 
-- [<img src="https://run.pstmn.io/button.svg" alt="Run In Postman" style="width: 128px; height: 32px;">](https://god.gw.postman.com/run-collection/5146551-e6aac565-e0e2-46df-acff-2607a51bbd04?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-e6aac565-e0e2-46df-acff-2607a51bbd04%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124)
+- [<img src="https://run.pstmn.io/button.svg" alt="Run In Postman" style="width: 128px; height: 32px;">](https://app.getpostman.com/run-collection/5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124)
 </details>
 
 ## Environment Variables

+ 2 - 2
README.ru_RU.md

@@ -482,7 +482,7 @@ WARP встроен, и дополнительная установка не т
 
 #### Использование
 
-- [API документация](https://documenter.getpostman.com/view/5146551/2sAXxP8Y12)
+- [API документация](https://www.postman.com/hsanaei/3x-ui/collection/q1l5l0u/3x-ui)
 - `/login` с `POST`-данными: `{username: '', password: ''}` для входа
 - `/panel/api/inbounds` это базовый путь для следующих действий:
 
@@ -516,7 +516,7 @@ WARP встроен, и дополнительная установка не т
 </details>
 
 
-- [<img src="https://run.pstmn.io/button.svg" alt="Run In Postman" style="width: 128px; height: 32px;">](https://god.gw.postman.com/run-collection/5146551-e6aac565-e0e2-46df-acff-2607a51bbd04?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-e6aac565-e0e2-46df-acff-2607a51bbd04%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124)
+- [<img src="https://run.pstmn.io/button.svg" alt="Run In Postman" style="width: 128px; height: 32px;">](https://app.getpostman.com/run-collection/5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124)
 </details>
 
 ## Переменные среды

+ 2 - 2
README.zh_CN.md

@@ -477,7 +477,7 @@ Web 面板通过 Telegram Bot 支持每日流量、面板登录、数据库备
 
 #### 使用
 
-- [API 文档](https://documenter.getpostman.com/view/5146551/2sAXxP8Y12)
+- [API 文档](https://www.postman.com/hsanaei/3x-ui/collection/q1l5l0u/3x-ui)
 - `/login` 使用 `POST` 用户名称 & 密码: `{username: '', password: ''}` 登录
 - `/panel/api/inbounds` 以下操作的基础:
 
@@ -507,7 +507,7 @@ Web 面板通过 Telegram Bot 支持每日流量、面板登录、数据库备
 - `client.password`  TROJAN
 - `client.email`  Shadowsocks
 
-- [<img src="https://run.pstmn.io/button.svg" alt="Run In Postman" style="width: 128px; height: 32px;">](https://god.gw.postman.com/run-collection/5146551-e6aac565-e0e2-46df-acff-2607a51bbd04?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-e6aac565-e0e2-46df-acff-2607a51bbd04%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124)
+- [<img src="https://run.pstmn.io/button.svg" alt="Run In Postman" style="width: 128px; height: 32px;">](https://app.getpostman.com/run-collection/5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124)
 </details>
 
 ## 环境变量

+ 1 - 1
config/version

@@ -1 +1 @@
-2.4.6
+2.4.7

+ 4 - 0
sub/subService.go

@@ -238,6 +238,7 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string {
 			headers, _ := splithttp["headers"].(map[string]interface{})
 			obj["host"] = searchHost(headers)
 		}
+		obj["mode"] = splithttp["mode"].(string)
 	}
 	security, _ := stream["security"].(string)
 	obj["tls"] = security
@@ -389,6 +390,7 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
 			headers, _ := splithttp["headers"].(map[string]interface{})
 			params["host"] = searchHost(headers)
 		}
+		params["mode"] = splithttp["mode"].(string)
 	}
 	security, _ := stream["security"].(string)
 	if security == "tls" {
@@ -586,6 +588,7 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
 			headers, _ := splithttp["headers"].(map[string]interface{})
 			params["host"] = searchHost(headers)
 		}
+		params["mode"] = splithttp["mode"].(string)
 	}
 	security, _ := stream["security"].(string)
 	if security == "tls" {
@@ -783,6 +786,7 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st
 			headers, _ := splithttp["headers"].(map[string]interface{})
 			params["host"] = searchHost(headers)
 		}
+		params["mode"] = splithttp["mode"].(string)
 	}
 
 	security, _ := stream["security"].(string)

+ 17 - 2
web/assets/js/model/inbound.js

@@ -113,6 +113,12 @@ const USERS_SECURITY = {
     ZERO: "zero",
 };
 
+const MODE_OPTION = {
+    AUTO: "auto",
+    PACKET_UP: "packet-up",
+    STREAM_UP: "stream-up",
+};
+
 Object.freeze(Protocols);
 Object.freeze(SSMethods);
 Object.freeze(TLS_FLOW_CONTROL);
@@ -125,6 +131,7 @@ Object.freeze(USAGE_OPTION);
 Object.freeze(DOMAIN_STRATEGY_OPTION);
 Object.freeze(TCP_CONGESTION_OPTION);
 Object.freeze(USERS_SECURITY);
+Object.freeze(MODE_OPTION);
 
 class XrayCommonClass {
 
@@ -528,7 +535,8 @@ class SplitHTTPStreamSettings extends XrayCommonClass {
             maxConnections: 0,
             cMaxReuseTimes: "64-128",
             cMaxLifetimeMs: 0
-        }
+        },
+        mode = MODE_OPTION.AUTO,
     ) {
         super();
         this.path = path;
@@ -540,6 +548,7 @@ class SplitHTTPStreamSettings extends XrayCommonClass {
         this.noSSEHeader = noSSEHeader;
         this.xPaddingBytes = xPaddingBytes;
         this.xmux = xmux;
+        this.mode = mode;
     }
 
     addHeader(name, value) {
@@ -561,6 +570,7 @@ class SplitHTTPStreamSettings extends XrayCommonClass {
             json.noSSEHeader,
             json.xPaddingBytes,
             json.xmux,
+            json.mode,
         );
     }
 
@@ -579,7 +589,8 @@ class SplitHTTPStreamSettings extends XrayCommonClass {
                 maxConnections: this.xmux.maxConnections,
                 cMaxReuseTimes: this.xmux.cMaxReuseTimes,
                 cMaxLifetimeMs: this.xmux.cMaxLifetimeMs
-            }
+            },
+            mode: this.mode,
         };
     }
 }
@@ -1329,6 +1340,7 @@ class Inbound extends XrayCommonClass {
             const splithttp = this.stream.splithttp;
             obj.path = splithttp.path;
             obj.host = splithttp.host?.length > 0 ? splithttp.host : this.getHeader(splithttp, 'host');
+            obj.mode = splithttp.mode;
         }
 
         if (security === 'tls') {
@@ -1401,6 +1413,7 @@ class Inbound extends XrayCommonClass {
                 const splithttp = this.stream.splithttp;
                 params.set("path", splithttp.path);
                 params.set("host", splithttp.host?.length > 0 ? splithttp.host : this.getHeader(splithttp, 'host'));
+                params.set("mode", splithttp.mode);
                 break;
         }
 
@@ -1504,6 +1517,7 @@ class Inbound extends XrayCommonClass {
                 const splithttp = this.stream.splithttp;
                 params.set("path", splithttp.path);
                 params.set("host", splithttp.host?.length > 0 ? splithttp.host : this.getHeader(splithttp, 'host'));
+                params.set("mode", splithttp.mode);
                 break;
         }
 
@@ -1586,6 +1600,7 @@ class Inbound extends XrayCommonClass {
                 const splithttp = this.stream.splithttp;
                 params.set("path", splithttp.path);
                 params.set("host", splithttp.host?.length > 0 ? splithttp.host : this.getHeader(splithttp, 'host'));
+                params.set("mode", splithttp.mode);
                 break;
         }
 

+ 17 - 3
web/assets/js/model/outbound.js

@@ -77,6 +77,12 @@ const USERS_SECURITY = {
     ZERO: "zero",
 };
 
+const MODE_OPTION = {
+    AUTO: "auto",
+    PACKET_UP: "packet-up",
+    STREAM_UP: "stream-up",
+};
+
 Object.freeze(Protocols);
 Object.freeze(SSMethods);
 Object.freeze(TLS_FLOW_CONTROL);
@@ -85,6 +91,7 @@ Object.freeze(ALPN_OPTION);
 Object.freeze(OutboundDomainStrategies);
 Object.freeze(WireguardDomainStrategy);
 Object.freeze(USERS_SECURITY);
+Object.freeze(MODE_OPTION);
 
 
 class CommonClass {
@@ -320,16 +327,22 @@ class HttpUpgradeStreamSettings extends CommonClass {
 }
 
 class SplitHTTPStreamSettings extends CommonClass {
-    constructor(path = '/', host = '') {
+    constructor(
+        path = '/',
+        host = '',
+        mode = '',
+    ) {
         super();
         this.path = path;
         this.host = host;
+        this.mode = mode;
     }
 
     static fromJson(json = {}) {
         return new SplitHTTPStreamSettings(
             json.path,
             json.host,
+            json.mode,
         );
     }
 
@@ -337,6 +350,7 @@ class SplitHTTPStreamSettings extends CommonClass {
         return {
             path: this.path,
             host: this.host,
+            mode: this.mode,
         };
     }
 }
@@ -710,7 +724,7 @@ class Outbound extends CommonClass {
         } else if (network === 'httpupgrade') {
             stream.httpupgrade = new HttpUpgradeStreamSettings(json.path, json.host);
         } else if (network === 'splithttp') {
-            stream.splithttp = new SplitHTTPStreamSettings(json.path, json.host);
+            stream.splithttp = new SplitHTTPStreamSettings(json.path, json.host, json.mode);
         }
 
         if (json.tls && json.tls == 'tls') {
@@ -754,7 +768,7 @@ class Outbound extends CommonClass {
         } else if (type === 'httpupgrade') {
             stream.httpupgrade = new HttpUpgradeStreamSettings(path, host);
         } else if (type === 'splithttp') {
-            stream.splithttp = new SplitHTTPStreamSettings(path, host);
+            stream.splithttp = new SplitHTTPStreamSettings(path, host, mode);
         }
 
         if (security == 'tls') {

+ 5 - 0
web/html/xui/form/outbound.html

@@ -380,6 +380,11 @@
           <a-form-item label='{{ i18n "path" }}'>
             <a-input v-model.trim="outbound.stream.splithttp.path"></a-input>
           </a-form-item>
+          <a-form-item label='Mode'>
+            <a-select v-model="outbound.stream.splithttp.mode" :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>
         </template>
       </template>
 

+ 6 - 0
web/html/xui/form/stream/stream_splithttp.html

@@ -22,6 +22,12 @@
             </a-input>
         </a-input-group>
     </a-form-item>
+    <a-form-item label='Mode'>
+        <a-select v-model="inbound.stream.splithttp.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 label="Max Concurrent Upload">
         <a-input v-model.trim="inbound.stream.splithttp.scMaxConcurrentPosts"></a-input>
     </a-form-item>

+ 8 - 0
web/html/xui/inbound_info_modal.html

@@ -58,6 +58,14 @@
               </td>
             </tr>
           </template>
+          <template v-if="inbound.isSplithttp">
+            <tr>
+              <td>Mode</td>
+              <td>
+                <a-tag>[[ inbound.stream.splithttp.mode ]]</a-tag>
+              </td>
+            </tr>
+          </template>
           <template v-if="inbound.isKcp">
             <tr>
               <td>kcp {{ i18n "encryption" }}</td>