diff --git a/pulsaradmin/pkg/admin/brokers.go b/pulsaradmin/pkg/admin/brokers.go index 8bf916b264..12c3527b88 100644 --- a/pulsaradmin/pkg/admin/brokers.go +++ b/pulsaradmin/pkg/admin/brokers.go @@ -20,6 +20,7 @@ package admin import ( "context" "fmt" + "net/url" "strings" "github.com/apache/pulsar-client-go/pulsaradmin/pkg/utils" @@ -187,7 +188,7 @@ func (b *broker) UpdateDynamicConfiguration(configName, configValue string) erro } func (b *broker) UpdateDynamicConfigurationWithContext(ctx context.Context, configName, configValue string) error { - value := fmt.Sprintf("/configuration/%s/%s", configName, configValue) + value := fmt.Sprintf("/configuration/%s/%s", configName, url.PathEscape(configValue)) endpoint := b.pulsar.endpointWithFullPath(b.basePath, value) return b.pulsar.Client.PostWithContext(ctx, endpoint, nil) } diff --git a/pulsaradmin/pkg/admin/brokers_test.go b/pulsaradmin/pkg/admin/brokers_test.go index 7b56213b0b..de886d3522 100644 --- a/pulsaradmin/pkg/admin/brokers_test.go +++ b/pulsaradmin/pkg/admin/brokers_test.go @@ -20,9 +20,11 @@ package admin import ( "context" "encoding/json" + "io" "net/http" "net/url" "os" + "strings" "testing" "github.com/apache/pulsar-client-go/pulsaradmin/pkg/admin/auth" @@ -30,8 +32,15 @@ import ( "github.com/apache/pulsar-client-go/pulsaradmin/pkg/rest" "github.com/apache/pulsar-client-go/pulsaradmin/pkg/utils" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) +type roundTripFunc func(*http.Request) (*http.Response, error) + +func (f roundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) { + return f(req) +} + func TestBrokerHealthCheckWithTopicVersion(t *testing.T) { readFile, err := os.ReadFile("../../../integration-tests/tokens/admin-token") assert.NoError(t, err) @@ -98,6 +107,34 @@ func TestUpdateDynamicConfiguration(t *testing.T) { assert.NotEmpty(t, configurations) } +func TestUpdateDynamicConfigurationEscapesConfigValue(t *testing.T) { + admin := &pulsarClient{ + APIVersion: config.V2, + Client: &rest.Client{ + ServiceURL: "http://example.com", + HTTPClient: &http.Client{ + Transport: roundTripFunc(func(r *http.Request) (*http.Response, error) { + require.Equal(t, http.MethodPost, r.Method) + require.Equal( + t, + "/admin/v2/brokers/configuration/testConfigName/public%2Fdefault", + r.URL.EscapedPath(), + ) + return &http.Response{ + StatusCode: http.StatusNoContent, + Body: io.NopCloser(strings.NewReader("")), + Header: make(http.Header), + Request: r, + }, nil + }), + }, + }, + } + + err := admin.Brokers().UpdateDynamicConfiguration("testConfigName", "public/default") + require.NoError(t, err) +} + func TestUpdateDynamicConfigurationWithCustomURL(t *testing.T) { readFile, err := os.ReadFile("../../../integration-tests/tokens/admin-token") assert.NoError(t, err) diff --git a/pulsaradmin/pkg/rest/client.go b/pulsaradmin/pkg/rest/client.go index 82e460b1f7..bce7e693f2 100644 --- a/pulsaradmin/pkg/rest/client.go +++ b/pulsaradmin/pkg/rest/client.go @@ -62,6 +62,10 @@ func (c *Client) newRequest(method, path string) (*request, error) { User: base.User, Host: base.Host, Path: endpoint(base.Path, u.Path), + RawPath: endpoint( + base.EscapedPath(), + u.EscapedPath(), + ), }, params: make(url.Values), }