Browse Source

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

Fixes https://github.com/XTLS/Xray-core/issues/4287
nobody 9 months ago
parent
commit
66dd7808b6
2 changed files with 150 additions and 108 deletions
  1. 34 23
      common/reflect/marshal.go
  2. 116 85
      common/reflect/marshal_test.go

+ 34 - 23
common/reflect/marshal.go

@@ -5,7 +5,6 @@ import (
 	"encoding/json"
 	"fmt"
 	"reflect"
-	"slices"
 	"strings"
 
 	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{} {
+	if v == nil {
+		return nil
+	}
 	tmsg, err := v.GetInstance()
 	if err != 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 {
-	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
 	} else if !isValueKind(rv.Kind()) && rv.IsNil() {
 		return true
@@ -182,6 +186,12 @@ func marshalKnownType(v interface{}, ignoreNullValue bool, insertTypeInfo bool)
 	case *conf.PortList:
 		cpl := v.(*conf.PortList)
 		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:
 		if addr := v.(cnet.Address); addr != nil {
 			return addr.String(), true
@@ -192,28 +202,29 @@ func marshalKnownType(v interface{}, ignoreNullValue bool, insertTypeInfo bool)
 	}
 }
 
-var valueKinds = []reflect.Kind{
-	reflect.Bool,
-	reflect.Int,
-	reflect.Int8,
-	reflect.Int16,
-	reflect.Int32,
-	reflect.Int64,
-	reflect.Uint,
-	reflect.Uint8,
-	reflect.Uint16,
-	reflect.Uint32,
-	reflect.Uint64,
-	reflect.Uintptr,
-	reflect.Float32,
-	reflect.Float64,
-	reflect.Complex64,
-	reflect.Complex128,
-	reflect.String,
-}
-
 func isValueKind(kind reflect.Kind) bool {
-	return slices.Contains(valueKinds, kind)
+	switch kind {
+	case reflect.Bool,
+		reflect.Int,
+		reflect.Int8,
+		reflect.Int16,
+		reflect.Int32,
+		reflect.Int64,
+		reflect.Uint,
+		reflect.Uint8,
+		reflect.Uint16,
+		reflect.Uint32,
+		reflect.Uint64,
+		reflect.Uintptr,
+		reflect.Float32,
+		reflect.Float64,
+		reflect.Complex64,
+		reflect.Complex128,
+		reflect.String:
+		return true
+	default:
+		return false
+	}
 }
 
 func marshalInterface(v interface{}, ignoreNullValue bool, insertTypeInfo bool) interface{} {

+ 116 - 85
common/reflect/marshal_test.go

@@ -116,98 +116,129 @@ func TestMarshalConfigJson(t *testing.T) {
 		"system",
 		"inboundDownlink",
 		"outboundUplink",
+		"XHTTP_IN",
+		"\"host\": \"bing.com\"",
+		"scMaxEachPostBytes",
+		"\"from\": 100",
+		"\"to\": 1000",
+		"\"from\": 1000000",
+		"\"to\": 1000000",
 	}
 	for _, kw := range keywords {
 		if !strings.Contains(tc, kw) {
-			t.Error("marshaled config error")
+			t.Log("config.json:", tc)
+			t.Error("keyword not found:", kw)
+			break
 		}
 	}
 }
 
 func getConfig() string {
 	return `{
-		"log": {
-		  "loglevel": "debug"
-		},
-		"stats": {},
-		"policy": {
-		  "levels": {
-			"0": {
-			  "statsUserUplink": true,
-			  "statsUserDownlink": true
-			}
-		  },
-		  "system": {
-			"statsInboundUplink": true,
-			"statsInboundDownlink": true,
-			"statsOutboundUplink": true,
-			"statsOutboundDownlink": true
-		  }
-		},
-		"inbounds": [
-		  {
-			"tag": "agentin",
-			"protocol": "http",
-			"port": 8080,
-			"listen": "127.0.0.1",
-			"settings": {}
-		  },
-		  {
-			"listen": "127.0.0.1",
-			"port": 10085,
-			"protocol": "dokodemo-door",
-			"settings": {
-			  "address": "127.0.0.1"
-			},
-			"tag": "api-in"
-		  }
-		],
-		"api": {
-		  "tag": "api",
-		  "services": [
-			"HandlerService",
-			"StatsService"
-		  ]
-		},
-		"routing": {
-		  "rules": [
-			{
-			  "inboundTag": [
-				"api-in"
-			  ],
-			  "outboundTag": "api",
-			  "type": "field"
-			}
-		  ],
-		  "domainStrategy": "AsIs"
-		},
-		"outbounds": [
-		  {
-			"protocol": "vless",
-			"settings": {
-			  "vnext": [
-				{
-				  "address": "1.2.3.4",
-				  "port": 1234,
-				  "users": [
-					{
-					  "id": "4784f9b8-a879-4fec-9718-ebddefa47750",
-					  "encryption": "none"
-					}
-				  ]
-				}
-			  ]
-			},
-			"tag": "agentout",
-			"streamSettings": {
-			  "network": "ws",
-			  "security": "none",
-			  "wsSettings": {
-				"path": "/?ed=2048",
-				"host": "bing.com"
-			  }
-			}
-		  }
-		]
-	  }`
+  "log": {
+    "loglevel": "debug"
+  },
+  "stats": {},
+  "policy": {
+    "levels": {
+      "0": {
+        "statsUserUplink": true,
+        "statsUserDownlink": true
+      }
+    },
+    "system": {
+      "statsInboundUplink": true,
+      "statsInboundDownlink": true,
+      "statsOutboundUplink": true,
+      "statsOutboundDownlink": true
+    }
+  },
+  "inbounds": [
+    {
+      "tag": "agentin",
+      "protocol": "http",
+      "port": 18080,
+      "listen": "127.0.0.1",
+      "settings": {}
+    },
+    {
+      "listen": "127.0.0.1",
+      "port": 10085,
+      "protocol": "dokodemo-door",
+      "settings": {
+        "address": "127.0.0.1"
+      },
+      "tag": "api-in"
+    }
+  ],
+  "api": {
+    "tag": "api",
+    "services": [
+      "HandlerService",
+      "StatsService"
+    ]
+  },
+  "routing": {
+    "rules": [
+      {
+        "inboundTag": [
+          "api-in"
+        ],
+        "outboundTag": "api",
+        "type": "field"
+      }
+    ],
+    "domainStrategy": "AsIs"
+  },
+  "outbounds": [
+    {
+      "protocol": "vless",
+      "settings": {
+        "vnext": [
+          {
+            "address": "1.2.3.4",
+            "port": 1234,
+            "users": [
+              {
+                "id": "4784f9b8-a879-4fec-9718-ebddefa47750",
+                "encryption": "none"
+              }
+            ]
+          }
+        ]
+      },
+      "tag": "XHTTP_IN",
+      "streamSettings": {
+        "network": "xhttp",
+        "xhttpSettings": {
+          "host": "bing.com",
+          "path": "/xhttp_client_upload",
+          "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
+      }
+    }
+  ]
+}`
 }