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

janhoy pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/branch_9x by this push:
     new 4cfbe6d3ff3 SOLR-18282 Improve ZookeeperInfoHandler path normalization 
(branch_9x)
4cfbe6d3ff3 is described below

commit 4cfbe6d3ff33ace95f8a05a2fe67b19c93c4d2e9
Author: Jan Høydahl <[email protected]>
AuthorDate: Sun Jun 28 01:51:41 2026 +0200

    SOLR-18282 Improve ZookeeperInfoHandler path normalization (branch_9x)
---
 .../solr/handler/admin/ZookeeperInfoHandler.java   | 37 ++++-------
 .../handler/admin/ZookeeperInfoHandlerTest.java    | 72 ++++++++++++++++++++++
 2 files changed, 85 insertions(+), 24 deletions(-)

diff --git 
a/solr/core/src/java/org/apache/solr/handler/admin/ZookeeperInfoHandler.java 
b/solr/core/src/java/org/apache/solr/handler/admin/ZookeeperInfoHandler.java
index ed46a25f20f..3b09a3420c9 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/ZookeeperInfoHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/ZookeeperInfoHandler.java
@@ -16,6 +16,7 @@
  */
 package org.apache.solr.handler.admin;
 
+import static 
org.apache.solr.common.cloud.ZkStateReader.SOLR_SECURITY_CONF_PATH;
 import static org.apache.solr.common.params.CommonParams.OMIT_HEADER;
 import static org.apache.solr.common.params.CommonParams.PATH;
 import static org.apache.solr.common.params.CommonParams.WT;
@@ -82,6 +83,7 @@ import org.slf4j.LoggerFactory;
  */
 public final class ZookeeperInfoHandler extends RequestHandlerBase {
   private static final String PARAM_DETAIL = "detail";
+  private static final String PARAM_DUMP = "dump";
   private final CoreContainer cores;
 
   private static final Logger log = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@@ -108,8 +110,8 @@ public final class ZookeeperInfoHandler extends 
RequestHandlerBase {
   public Name getPermissionName(AuthorizationContext request) {
     var params = request.getParams();
     String path = normalizePath(params.get(PATH, ""));
-    String detail = params.get(PARAM_DETAIL, "false");
-    if ("/security.json".equalsIgnoreCase(path) && 
"true".equalsIgnoreCase(detail)) {
+    if (path.equals(SOLR_SECURITY_CONF_PATH)
+        || (params.getBool(PARAM_DUMP, false) && "/".equals(path))) {
       return Name.SECURITY_READ_PERM;
     } else {
       return Name.ZK_READ_PERM;
@@ -374,17 +376,14 @@ public final class ZookeeperInfoHandler extends 
RequestHandlerBase {
       }
     }
 
-    String path = params.get(PATH);
+    String path = normalizePath(params.get(PATH));
 
     if (params.get("addr") != null) {
       throw new SolrException(ErrorCode.BAD_REQUEST, "Illegal parameter 
\"addr\"");
     }
 
-    String detailS = params.get(PARAM_DETAIL);
-    boolean detail = detailS != null && detailS.equals("true");
-
-    String dumpS = params.get("dump");
-    boolean dump = dumpS != null && dumpS.equals("true");
+    boolean detail = params.getBool(PARAM_DETAIL, false);
+    boolean dump = params.getBool(PARAM_DUMP, false);
 
     int start = params.getInt("start", 0); // Note start ignored if rows not 
specified
     int rows = params.getInt("rows", -1);
@@ -428,8 +427,12 @@ public final class ZookeeperInfoHandler extends 
RequestHandlerBase {
   }
 
   @SuppressForbidden(reason = "JDK String class doesn't offer a stripEnd 
equivalent")
-  private String normalizePath(String path) {
-    return StringUtils.stripEnd(path, "/");
+  String normalizePath(String path) {
+    if (path == null) {
+      return "/";
+    }
+    String normalized = StringUtils.stripEnd(path.trim(), "/");
+    return normalized.isEmpty() ? "/" : normalized;
   }
 
   // 
--------------------------------------------------------------------------------------
@@ -474,20 +477,6 @@ public final class ZookeeperInfoHandler extends 
RequestHandlerBase {
         return;
       }
 
-      // normalize path
-      if (path == null) {
-        path = "/";
-      } else {
-        path = path.trim();
-        if (path.length() == 0) {
-          path = "/";
-        }
-      }
-
-      if (path.endsWith("/") && path.length() > 1) {
-        path = path.substring(0, path.length() - 1);
-      }
-
       int idx = path.lastIndexOf('/');
       String parent = idx >= 0 ? path.substring(0, idx) : path;
       if (parent.length() == 0) {
diff --git 
a/solr/core/src/test/org/apache/solr/handler/admin/ZookeeperInfoHandlerTest.java
 
b/solr/core/src/test/org/apache/solr/handler/admin/ZookeeperInfoHandlerTest.java
new file mode 100644
index 00000000000..5d82405372f
--- /dev/null
+++ 
b/solr/core/src/test/org/apache/solr/handler/admin/ZookeeperInfoHandlerTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.solr.handler.admin;
+
+import java.io.IOException;
+import org.apache.solr.client.solrj.SolrClient;
+import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.JsonMapResponseParser;
+import org.apache.solr.client.solrj.request.GenericSolrRequest;
+import org.apache.solr.cloud.SolrCloudTestCase;
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.util.NamedList;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/** Basic tests for {@link ZookeeperInfoHandler} */
+public class ZookeeperInfoHandlerTest extends SolrCloudTestCase {
+
+  @BeforeClass
+  public static void setupCluster() throws Exception {
+    configureCluster(1).addConfig("conf", 
configset("cloud-minimal")).configure();
+  }
+
+  @Test
+  public void testZkInfoHandlerDetailView() throws SolrServerException, 
IOException {
+    SolrClient client = cluster.getSolrClient();
+
+    ModifiableSolrParams params = new ModifiableSolrParams();
+    params.set(CommonParams.PATH, "/");
+    params.set("detail", "true");
+    GenericSolrRequest req =
+        new GenericSolrRequest(SolrRequest.METHOD.GET, "/admin/zookeeper", 
params);
+    req.setResponseParser(new JsonMapResponseParser());
+
+    NamedList<Object> response = client.request(req);
+    assertNotNull("Response should not be null", response);
+
+    // ZK handler should return 'znode' for detail requests
+    assertNotNull(response.get("znode"));
+  }
+
+  @Test
+  public void testNormalizePath() {
+    ZookeeperInfoHandler handler =
+        new 
ZookeeperInfoHandler(cluster.getJettySolrRunner(0).getCoreContainer());
+
+    assertEquals("/foo", handler.normalizePath(" /foo"));
+    assertEquals("/foo", handler.normalizePath("/foo "));
+    assertEquals("/foo", handler.normalizePath("/foo/"));
+    assertEquals("/foo", handler.normalizePath("/foo//"));
+    assertEquals("/", handler.normalizePath(null));
+    assertEquals("/", handler.normalizePath(""));
+    assertEquals("/", handler.normalizePath("  "));
+    assertEquals("/", handler.normalizePath("/"));
+  }
+}

Reply via email to