Commands: Fix dumping merged config for XHTTP (#4290)

Fixes https://github.com/XTLS/Xray-core/issues/4287
This commit is contained in:
nobody 2025-01-17 18:40:36 +08:00 committed by GitHub
parent f1ff454e67
commit 66dd7808b6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 150 additions and 108 deletions

View File

@ -5,7 +5,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"reflect" "reflect"
"slices"
"strings" "strings"
cnet "github.com/xtls/xray-core/common/net" cnet "github.com/xtls/xray-core/common/net"
@ -32,6 +31,9 @@ func JSONMarshalWithoutEscape(t interface{}) ([]byte, error) {
} }
func marshalTypedMessage(v *cserial.TypedMessage, ignoreNullValue bool, insertTypeInfo bool) interface{} { func marshalTypedMessage(v *cserial.TypedMessage, ignoreNullValue bool, insertTypeInfo bool) interface{} {
if v == nil {
return nil
}
tmsg, err := v.GetInstance() tmsg, err := v.GetInstance()
if err != nil { if err != nil {
return nil return nil
@ -56,7 +58,9 @@ func marshalSlice(v reflect.Value, ignoreNullValue bool, insertTypeInfo bool) in
} }
func isNullValue(f reflect.StructField, rv reflect.Value) bool { func isNullValue(f reflect.StructField, rv reflect.Value) bool {
if rv.Kind() == reflect.String && rv.Len() == 0 { if rv.Kind() == reflect.Struct {
return false
} else if rv.Kind() == reflect.String && rv.Len() == 0 {
return true return true
} else if !isValueKind(rv.Kind()) && rv.IsNil() { } else if !isValueKind(rv.Kind()) && rv.IsNil() {
return true return true
@ -182,6 +186,12 @@ func marshalKnownType(v interface{}, ignoreNullValue bool, insertTypeInfo bool)
case *conf.PortList: case *conf.PortList:
cpl := v.(*conf.PortList) cpl := v.(*conf.PortList)
return serializePortList(cpl.Build()) return serializePortList(cpl.Build())
case conf.Int32Range:
i32rng := v.(conf.Int32Range)
if i32rng.Left == i32rng.Right {
return i32rng.Left, true
}
return i32rng.String(), true
case cnet.Address: case cnet.Address:
if addr := v.(cnet.Address); addr != nil { if addr := v.(cnet.Address); addr != nil {
return addr.String(), true return addr.String(), true
@ -192,8 +202,9 @@ func marshalKnownType(v interface{}, ignoreNullValue bool, insertTypeInfo bool)
} }
} }
var valueKinds = []reflect.Kind{ func isValueKind(kind reflect.Kind) bool {
reflect.Bool, switch kind {
case reflect.Bool,
reflect.Int, reflect.Int,
reflect.Int8, reflect.Int8,
reflect.Int16, reflect.Int16,
@ -209,11 +220,11 @@ var valueKinds = []reflect.Kind{
reflect.Float64, reflect.Float64,
reflect.Complex64, reflect.Complex64,
reflect.Complex128, reflect.Complex128,
reflect.String, reflect.String:
return true
default:
return false
} }
func isValueKind(kind reflect.Kind) bool {
return slices.Contains(valueKinds, kind)
} }
func marshalInterface(v interface{}, ignoreNullValue bool, insertTypeInfo bool) interface{} { func marshalInterface(v interface{}, ignoreNullValue bool, insertTypeInfo bool) interface{} {

View File

@ -116,10 +116,19 @@ func TestMarshalConfigJson(t *testing.T) {
"system", "system",
"inboundDownlink", "inboundDownlink",
"outboundUplink", "outboundUplink",
"XHTTP_IN",
"\"host\": \"bing.com\"",
"scMaxEachPostBytes",
"\"from\": 100",
"\"to\": 1000",
"\"from\": 1000000",
"\"to\": 1000000",
} }
for _, kw := range keywords { for _, kw := range keywords {
if !strings.Contains(tc, kw) { if !strings.Contains(tc, kw) {
t.Error("marshaled config error") t.Log("config.json:", tc)
t.Error("keyword not found:", kw)
break
} }
} }
} }
@ -148,7 +157,7 @@ func getConfig() string {
{ {
"tag": "agentin", "tag": "agentin",
"protocol": "http", "protocol": "http",
"port": 8080, "port": 18080,
"listen": "127.0.0.1", "listen": "127.0.0.1",
"settings": {} "settings": {}
}, },
@ -198,14 +207,36 @@ func getConfig() string {
} }
] ]
}, },
"tag": "agentout", "tag": "XHTTP_IN",
"streamSettings": { "streamSettings": {
"network": "ws", "network": "xhttp",
"security": "none", "xhttpSettings": {
"wsSettings": { "host": "bing.com",
"path": "/?ed=2048", "path": "/xhttp_client_upload",
"host": "bing.com" "mode": "auto",
"extra": {
"noSSEHeader": false,
"scMaxEachPostBytes": 1000000,
"scMaxBufferedPosts": 30,
"xPaddingBytes": "100-1000"
} }
},
"sockopt": {
"tcpFastOpen": true,
"acceptProxyProtocol": false,
"tcpcongestion": "bbr",
"tcpMptcp": true
}
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
],
"metadataOnly": false,
"routeOnly": true
} }
} }
] ]