mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-24 06:45:01 +03:00
fix(sub): pass numeric XMUX counts to Clash reuse-settings (#6843)
Inbound XMUX counts such as maxConnections are stored as JSON numbers, but buildXhttpClashOpts kept only string values, so the panel default maxConnections: 3 never reached Clash/Mihomo clients. Numeric values are now rendered as plain integers (FormatFloat, so 1000000 does not become 1e+06) and zero values are still dropped.
This commit is contained in:
@@ -1018,8 +1018,15 @@ func buildXhttpClashOpts(xhttp map[string]any) map[string]any {
|
||||
{"hMaxRequestTimes", "h-max-request-times"},
|
||||
{"hMaxReusableSecs", "h-max-reusable-secs"},
|
||||
} {
|
||||
if v, ok := xmux[f.src].(string); ok && v != "" {
|
||||
reuse[f.dst] = v
|
||||
v, ok := nonZeroShareValue(xmux[f.src])
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if n, isFloat := v.(float64); isFloat {
|
||||
// JSON numbers decode as float64, and %v would render 1000000 as "1e+06".
|
||||
reuse[f.dst] = strconv.FormatFloat(n, 'f', -1, 64)
|
||||
} else {
|
||||
reuse[f.dst] = fmt.Sprint(v)
|
||||
}
|
||||
}
|
||||
if v, ok := nonZeroShareValue(xmux["hKeepAlivePeriod"]); ok {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package sub
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
@@ -798,6 +799,37 @@ func TestBuildXhttpClashOpts_XmuxMapsToReuseSettings(t *testing.T) {
|
||||
t.Error("reuse-settings should not appear when only hKeepAlivePeriod=0")
|
||||
}
|
||||
})
|
||||
|
||||
// Sub-test 5: numeric counts as json.Unmarshal yields them (#6841)
|
||||
t.Run("NumericXmux", func(t *testing.T) {
|
||||
cases := []struct {
|
||||
name, xmux string
|
||||
want map[string]any
|
||||
}{
|
||||
{
|
||||
name: "PanelDefaults",
|
||||
xmux: `{"maxConcurrency":"","maxConnections":3,"cMaxReuseTimes":0,"hMaxRequestTimes":"600-900","hMaxReusableSecs":"1800-3000","hKeepAlivePeriod":0}`,
|
||||
want: map[string]any{"max-connections": "3", "h-max-request-times": "600-900", "h-max-reusable-secs": "1800-3000"},
|
||||
},
|
||||
{
|
||||
name: "LargeCountNotExponent",
|
||||
xmux: `{"cMaxReuseTimes":1000000}`,
|
||||
want: map[string]any{"c-max-reuse-times": "1000000"},
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var xmux map[string]any
|
||||
if err := json.Unmarshal([]byte(tc.xmux), &xmux); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
opts := buildXhttpClashOpts(map[string]any{"path": "/", "xmux": xmux})
|
||||
if got := opts["reuse-settings"]; !reflect.DeepEqual(got, tc.want) {
|
||||
t.Errorf("reuse-settings = %#v, want %#v", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestBuildXhttpClashOpts_ServerOnlyFieldsExcluded(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user