fix: resolve padding_scheme decode error in WebSocket config sync

This commit is contained in:
xboard
2026-03-17 03:02:51 +08:00
parent 3e457e8ac6
commit 8f13a02ca8
3 changed files with 64 additions and 9 deletions
+21 -8
View File
@@ -8,6 +8,7 @@ import (
"log/slog" "log/slog"
"net/http" "net/http"
"net/url" "net/url"
"reflect"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@@ -145,19 +146,31 @@ func (c *Client) Report(traffic map[int][2]int64, alive map[int][]string, online
} }
// decodeWeakRaw decodes an interface (from JSON map) into a struct using weak type conversion. // decodeWeakRaw decodes an interface (from JSON map) into a struct using weak type conversion.
func decodeWeakRaw(input interface{}, output interface{}) error { func decodeWeakRaw(input map[string]interface{}, output interface{}) error {
config := &mapstructure.DecoderConfig{ config := &mapstructure.DecoderConfig{
Metadata: nil, Metadata: nil,
Result: output, Result: output,
WeaklyTypedInput: true, WeaklyTypedInput: true,
TagName: "json", // Follow JSON tags TagName: "json",
DecodeHook: mapstructure.ComposeDecodeHookFunc(
func(f, t reflect.Type, v interface{}) (interface{}, error) {
// Handle []interface{} -> StringOrArray
if t == reflect.TypeOf(StringOrArray("")) && f.Kind() == reflect.Slice {
arr, _ := v.([]interface{})
var strs []string
for _, x := range arr {
if s, ok := x.(string); ok {
strs = append(strs, s)
}
}
return StringOrArray(strings.Join(strs, "\n")), nil
}
return v, nil
},
mapstructure.StringToSliceHookFunc(","),
),
} }
decoder, _ := mapstructure.NewDecoder(config)
decoder, err := mapstructure.NewDecoder(config)
if err != nil {
return err
}
return decoder.Decode(input) return decoder.Decode(input)
} }
+42
View File
@@ -293,3 +293,45 @@ func TestClient_NodeTypeInQuery(t *testing.T) {
}) })
client.GetConfig() client.GetConfig()
} }
func TestStringOrArrayDecodeHook(t *testing.T) {
// Test case: []interface{} -> StringOrArray
input := map[string]interface{}{
"padding_scheme": []interface{}{"stop=8", "0=30-30", "1=100-400"},
}
type TestConfig struct {
PaddingScheme StringOrArray `json:"padding_scheme"`
}
var cfg TestConfig
if err := decodeWeakRaw(input, &cfg); err != nil {
t.Fatalf("decodeWeakRaw failed: %v", err)
}
want := "stop=8\n0=30-30\n1=100-400"
if string(cfg.PaddingScheme) != want {
t.Errorf("got %q, want %q", cfg.PaddingScheme, want)
}
}
func TestStringOrArrayDecodeHook_String(t *testing.T) {
// Test case: string -> StringOrArray
input := map[string]interface{}{
"padding_scheme": "stop=8\n0=30-30",
}
type TestConfig struct {
PaddingScheme StringOrArray `json:"padding_scheme"`
}
var cfg TestConfig
if err := decodeWeakRaw(input, &cfg); err != nil {
t.Fatalf("decodeWeakRaw failed: %v", err)
}
want := "stop=8\n0=30-30"
if string(cfg.PaddingScheme) != want {
t.Errorf("got %q, want %q", cfg.PaddingScheme, want)
}
}
+1 -1
View File
@@ -303,7 +303,7 @@ func (w *WSClient) handleDataEvent(msg wsMessage) {
// Helper to unmarshal and decode with weak Typing // Helper to unmarshal and decode with weak Typing
decodeData := func(data []byte, target interface{}) error { decodeData := func(data []byte, target interface{}) error {
var raw any var raw map[string]interface{}
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
return err return err
} }