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

JingsongLi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git


The following commit(s) were added to refs/heads/master by this push:
     new f6e3e31552 [api] Fix REST catalog double-encoding warehouse query 
parameter (#8792)
f6e3e31552 is described below

commit f6e3e315522a0e8eebca04288dce9143d92ed027
Author: eye-gu <[email protected]>
AuthorDate: Thu Jul 23 22:04:27 2026 +0800

    [api] Fix REST catalog double-encoding warehouse query parameter (#8792)
---
 .../main/java/org/apache/paimon/rest/RESTApi.java  |  2 +-
 .../paimon/rest/RESTApiWarehouseEncodingTest.java  | 86 ++++++++++++++++++++++
 2 files changed, 87 insertions(+), 1 deletion(-)

diff --git a/paimon-api/src/main/java/org/apache/paimon/rest/RESTApi.java 
b/paimon-api/src/main/java/org/apache/paimon/rest/RESTApi.java
index e8e1ff96c8..a49982d680 100644
--- a/paimon-api/src/main/java/org/apache/paimon/rest/RESTApi.java
+++ b/paimon-api/src/main/java/org/apache/paimon/rest/RESTApi.java
@@ -199,7 +199,7 @@ public class RESTApi {
             String warehouse = options.get(WAREHOUSE);
             Map<String, String> queryParams =
                     StringUtils.isNotEmpty(warehouse)
-                            ? ImmutableMap.of(WAREHOUSE.key(), 
RESTUtil.encodeString(warehouse))
+                            ? ImmutableMap.of(WAREHOUSE.key(), warehouse)
                             : ImmutableMap.of();
             options =
                     new Options(
diff --git 
a/paimon-core/src/test/java/org/apache/paimon/rest/RESTApiWarehouseEncodingTest.java
 
b/paimon-core/src/test/java/org/apache/paimon/rest/RESTApiWarehouseEncodingTest.java
new file mode 100644
index 0000000000..2e14f00ecb
--- /dev/null
+++ 
b/paimon-core/src/test/java/org/apache/paimon/rest/RESTApiWarehouseEncodingTest.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.paimon.rest;
+
+import org.apache.paimon.options.Options;
+import org.apache.paimon.rest.responses.ConfigResponse;
+
+import org.apache.paimon.shade.guava30.com.google.common.collect.ImmutableMap;
+
+import okhttp3.mockwebserver.MockResponse;
+import okhttp3.mockwebserver.MockWebServer;
+import okhttp3.mockwebserver.RecordedRequest;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.concurrent.TimeUnit;
+
+import static org.apache.paimon.options.CatalogOptions.WAREHOUSE;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class RESTApiWarehouseEncodingTest {
+
+    private MockWebServer server;
+
+    @AfterEach
+    void tearDown() throws Exception {
+        if (server != null) {
+            server.shutdown();
+        }
+    }
+
+    @Test
+    void testWarehouseQueryParameterNotDoubleEncoded() throws Exception {
+        // A warehouse path containing ':' and '/' exposes the encoding bug.
+        String warehouse = "file:///tmp/paimon-warehouse";
+
+        server = new MockWebServer();
+        server.start();
+
+        ConfigResponse config =
+                new ConfigResponse(
+                        ImmutableMap.of(
+                                WAREHOUSE.key(),
+                                warehouse,
+                                RESTCatalogInternalOptions.PREFIX.key(),
+                                "paimon"),
+                        ImmutableMap.of());
+        server.enqueue(
+                new MockResponse()
+                        .setResponseCode(200)
+                        .setBody(RESTApi.toJson(config))
+                        .addHeader("Content-Type", "application/json"));
+
+        Options options = new Options();
+        options.set(RESTCatalogOptions.URI, server.url("/").toString());
+        options.set(WAREHOUSE, warehouse);
+        options.set(RESTCatalogOptions.TOKEN, "token");
+        options.set(RESTCatalogOptions.TOKEN_PROVIDER, "bear");
+
+        // Triggers the /v1/config request inside the RESTApi constructor.
+        new RESTApi(options);
+
+        RecordedRequest request = server.takeRequest(10, TimeUnit.SECONDS);
+        String receivedWarehouse = 
request.getRequestUrl().queryParameter(WAREHOUSE.key());
+
+        // The query parameter is decoded once by the HTTP layer, so it must 
equal the original
+        // value. Double encoding on the client side makes it differ.
+        assertEquals(warehouse, receivedWarehouse, "warehouse query param was 
double-encoded");
+    }
+}

Reply via email to