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

lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git


The following commit(s) were added to refs/heads/rocketmq-studio by this push:
     new 27a4856d8 fix(proxy): probe IPv6 hosts without URI brackets (#5766)
27a4856d8 is described below

commit 27a4856d85c322f5dc533b9042fdd16f644341a4
Author: 0 <[email protected]>
AuthorDate: Mon Oct 19 18:39:48 2026 +0800

    fix(proxy): probe IPv6 hosts without URI brackets (#5766)
    
    Verified against `rocketmq-studio` at b88aedc34 before merging: 
缺陷仍在(`server/src/main/java/org/apache/rocketmq/studio/cluster/proxy/ProxyAddressService.java:182`、`:317`
 仍是裸 `matcher.group(1)`,无 `probeHost` helper;`
    
    merge-tree clean against the current trunk. Merged as-is (squash) per the 
maintainer review of 2026-10-19.
---
 .../studio/cluster/proxy/ProxyAddressService.java  | 16 ++++++++++++++--
 .../cluster/proxy/ProxyAddressServiceTest.java     | 22 ++++++++++++++++++++++
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/cluster/proxy/ProxyAddressService.java
 
b/server/src/main/java/org/apache/rocketmq/studio/cluster/proxy/ProxyAddressService.java
index cbe22ec14..96dcd9690 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/cluster/proxy/ProxyAddressService.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/cluster/proxy/ProxyAddressService.java
@@ -179,7 +179,7 @@ public class ProxyAddressService {
                 log.warn("Skipping malformed proxy address in topology: {}", 
addr);
                 continue;
             }
-            String host = matcher.group(1);
+            String host = probeHost(matcher.group(1));
             int grpcPort = Integer.parseInt(matcher.group(2));
             Integer remotingPort = deriveRemotingPort(grpcPort);
             tasks.add(new ProbeTask(addr, grpcPort, remotingPort,
@@ -259,6 +259,18 @@ public class ProxyAddressService {
                              CompletableFuture<ProxyHealthProbe.ProbeResult> 
remotingProbe) {
     }
 
+    /**
+     * Strips the brackets from a bracketed IPv6 literal before it reaches a 
socket connect:
+     * {@code new InetSocketAddress("[::1]", port)} leaves the address 
unresolved because the
+     * bracket form is URI syntax only, so an IPv6 proxy would always be 
reported DOWN. The
+     * registered address text keeps its brackets; only the probe target loses 
them.
+     */
+    private String probeHost(String host) {
+        return host.length() > 1 && host.startsWith("[") && host.endsWith("]")
+                ? host.substring(1, host.length() - 1)
+                : host;
+    }
+
     /**
      * Derives the counterpart port using the RocketMQ 5.0 default layout 
(remoting
      * {@code 8080} / gRPC {@code 8081}). Non-standard ports yield {@code 
null} because the
@@ -314,7 +326,7 @@ public class ProxyAddressService {
         String normalized = normalizeProxyAddr(proxy.getAddr(), "addr");
         Matcher matcher = PROXY_ADDR_PATTERN.matcher(normalized);
         matcher.matches();
-        String host = matcher.group(1);
+        String host = probeHost(matcher.group(1));
         int grpcPort = proxy.getGrpcPort() > 0 ? proxy.getGrpcPort() : 
Integer.parseInt(matcher.group(2));
         Integer remotingPort = proxy.getRemotingPort() > 0
                 ? Integer.valueOf(proxy.getRemotingPort()) : 
deriveRemotingPort(grpcPort);
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/cluster/proxy/ProxyAddressServiceTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/cluster/proxy/ProxyAddressServiceTest.java
index b9e71ae24..318b019ed 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/cluster/proxy/ProxyAddressServiceTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/cluster/proxy/ProxyAddressServiceTest.java
@@ -40,6 +40,7 @@ import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoInteractions;
@@ -292,6 +293,27 @@ class ProxyAddressServiceTest {
         assertThat(custom.isRemotingReachable()).isFalse();
     }
 
+    @Test
+    void buildTopologyShouldProbeBracketedIpv6HostWithoutBrackets() {
+        proxyAddressService.addProxyAddr("[::1]:8081");
+
+        when(healthProbe.probe(eq("::1"), anyInt(), anyInt()))
+                .thenReturn(ProxyHealthProbe.ProbeResult.reachable(1L));
+
+        List<ProxyTopologyVO> topology = proxyAddressService.buildTopology();
+
+        ProxyTopologyVO ipv6 = topology.stream()
+                .filter(node -> node.getProxyAddr().equals("[::1]:8081"))
+                .findFirst()
+                .orElseThrow();
+        // A socket connect cannot resolve a bracketed IPv6 literal, so the 
brackets must be
+        // stripped before the host reaches the probe; the reported address 
keeps them.
+        assertThat(ipv6.getStatus()).isEqualTo("UP");
+        verify(healthProbe).probe(eq("::1"), eq(8081), anyInt());
+        verify(healthProbe).probe(eq("::1"), eq(8080), anyInt());
+        verify(healthProbe, never()).probe(eq("[::1]"), anyInt(), anyInt());
+    }
+
     @Test
     void buildTopologyShouldProbeAddressesInParallelTest() {
         // Every probe blocks 300 ms; 4 addresses mean 8 probes, which would 
take

Reply via email to