This is an automated email from the ASF dual-hosted git repository.

marsevilspirit pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git


The following commit(s) were added to refs/heads/develop by this push:
     new ce295e4a4 fix: URL parameter loss issue in SetParams method (#3022)
ce295e4a4 is described below

commit ce295e4a468583051564251b556439ef7ca52b08
Author: CAICAII <39020005+caica...@users.noreply.github.com>
AuthorDate: Thu Sep 18 12:32:31 2025 +0800

    fix: URL parameter loss issue in SetParams method (#3022)
---
 common/url.go      | 19 +++++++++++++++----
 common/url_test.go | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/common/url.go b/common/url.go
index 09474729c..af6e68b08 100644
--- a/common/url.go
+++ b/common/url.go
@@ -737,13 +737,24 @@ func (c *URL) GetMethodParamBool(method string, key 
string, d bool) bool {
        return r
 }
 
-// SetParams will put all key-value pair into URL.
+// SetParams copies all key-value pairs into URL.
 // 1. if there already has same key, the value will be override
-// 2. it's not thread safe
+// 2. this method acquires a write lock and deep-copies the provided values to 
avoid data races
 // 3. think twice when you want to invoke this method
 func (c *URL) SetParams(m url.Values) {
-       for k := range m {
-               c.SetParam(k, m.Get(k))
+       c.paramsLock.Lock()
+       defer c.paramsLock.Unlock()
+       if c.params == nil {
+               c.params = url.Values{}
+       }
+       for k, vs := range m {
+               if len(vs) == 0 {
+                       delete(c.params, k)
+                       continue
+               }
+               copied := make([]string, len(vs))
+               copy(copied, vs)
+               c.params[k] = copied
        }
 }
 
diff --git a/common/url_test.go b/common/url_test.go
index 91880c266..5ee5197e2 100644
--- a/common/url_test.go
+++ b/common/url_test.go
@@ -592,3 +592,38 @@ func TestNewURLWithMultiAddr(t *testing.T) {
        assert.Nil(t, err)
        assert.Equal(t, "127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183", 
u4.Location)
 }
+
+func TestURLSetParamsMultiValue(t *testing.T) {
+       // Test case to verify multi-value parameter handling
+       u := &URL{}
+
+       // Create url.Values with multiple values for the same key
+       params := url.Values{}
+       params.Add("tag", "foo")
+       params.Add("tag", "bar")
+       params.Add("tag", "baz")
+       params.Set("single", "value")
+
+       // Set the parameters using the fixed implementation
+       u.SetParams(params)
+
+       // The implementation should preserve all values (multi-values stored 
internally)
+       got := u.GetParams()["tag"]
+       assert.ElementsMatch(t, []string{"foo", "bar", "baz"}, got)
+       assert.Equal(t, "value", u.GetParam("single", ""))
+
+       // Test with empty values
+       params2 := url.Values{}
+       params2.Add("empty", "")
+       params2.Add("empty", "value")
+       params2.Add("only_empty", "")
+
+       u2 := &URL{}
+       u2.SetParams(params2)
+
+       // Empty value slots are preserved as provided by caller
+       got2 := u2.GetParams()["empty"]
+       assert.ElementsMatch(t, []string{"", "value"}, got2)
+       got3 := u2.GetParams()["only_empty"]
+       assert.ElementsMatch(t, []string{""}, got3)
+}

Reply via email to