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

lizhimin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-clients.git


The following commit(s) were added to refs/heads/master by this push:
     new 3c6f6fab [ISSUE #1161] [Golang] Client support ipv6 hostip:port (#1162)
3c6f6fab is described below

commit 3c6f6fabdaddb91ef15b10e34c391d26be0e185b
Author: SHI <[email protected]>
AuthorDate: Wed Jan 14 11:01:05 2026 +0800

    [ISSUE #1161] [Golang] Client support ipv6 hostip:port (#1162)
    
    Co-authored-by: shixiaoxiao <[email protected]>
---
 golang/pkg/utils/utils.go      | 73 ++++++++++++++++++++++++++----------
 golang/pkg/utils/utils_test.go | 84 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 138 insertions(+), 19 deletions(-)

diff --git a/golang/pkg/utils/utils.go b/golang/pkg/utils/utils.go
index f9f29baa..9d30d5f4 100644
--- a/golang/pkg/utils/utils.go
+++ b/golang/pkg/utils/utils.go
@@ -91,37 +91,72 @@ func ParseTarget(target string) (*v2.Endpoints, error) {
        if strings.HasPrefix(target, "ip:///") {
                target = strings.TrimPrefix(target, "ip:///")
        }
+
        ret := &v2.Endpoints{
                Scheme: v2.AddressScheme_DOMAIN_NAME,
        }
+
        addressRawList := strings.Split(target, ";")
-       for _, path := range addressRawList {
-               if len(path) == 0 {
+       for _, item := range addressRawList {
+               item = strings.TrimSpace(item)
+               if item == "" {
                        continue
                }
-               address := &v2.Address{
-                       Host: "",
-                       Port: 80,
-               }
-               if u, err := url.Parse(path); err != nil {
-                       address.Host = path
-                       ret.Scheme = v2.AddressScheme_IPv4
-               } else {
-                       if u.Host != "" {
-                               address.Host = u.Host
+
+               var hostPort string
+
+               if idx := strings.Index(item, "://"); idx != -1 {
+                       u, err := url.Parse(item)
+                       if err != nil {
+                               return nil, fmt.Errorf("failed to parse URL %q: 
%w", item, err)
+                       }
+                       if u.Host == "" {
+                               return nil, fmt.Errorf("URL missing host: %q", 
item)
                        }
+                       hostPort = u.Host
+               } else {
+                       hostPort = item
+               }
+
+               host, portStr, err := net.SplitHostPort(hostPort)
+               if err != nil {
+                       return nil, fmt.Errorf("invalid host:port in %q (from 
%q): %w", hostPort, item, err)
                }
-               paths := strings.Split(path, ":")
-               if len(paths) > 1 {
-                       if port, err2 := strconv.ParseInt(paths[1], 10, 32); 
err2 == nil {
-                               address.Port = int32(port)
+
+               port, err := strconv.ParseInt(portStr, 10, 32)
+               if err != nil {
+                       return nil, fmt.Errorf("invalid port in %q: %w", 
portStr, err)
+               }
+
+               ip := net.ParseIP(host)
+               var addrScheme v2.AddressScheme
+               if ip != nil {
+                       if ip.To4() != nil {
+                               addrScheme = v2.AddressScheme_IPv4
+                       } else {
+                               addrScheme = v2.AddressScheme_IPv6
                        }
-                       address.Host = paths[0]
                } else {
-                       return nil, fmt.Errorf("parse target failed, 
target=%s", target)
+                       addrScheme = v2.AddressScheme_DOMAIN_NAME
+               }
+
+               address := &v2.Address{
+                       Host: host,
+                       Port: int32(port),
                }
                ret.Addresses = append(ret.Addresses, address)
+
+               if addrScheme == v2.AddressScheme_IPv6 {
+                       ret.Scheme = v2.AddressScheme_IPv6
+               } else if ret.Scheme == v2.AddressScheme_DOMAIN_NAME && 
addrScheme == v2.AddressScheme_IPv4 {
+                       ret.Scheme = v2.AddressScheme_IPv4
+               }
        }
+
+       if len(ret.Addresses) == 0 {
+               return nil, fmt.Errorf("no valid addresses found in target: 
%q", target)
+       }
+
        return ret, nil
 }
 
@@ -252,7 +287,7 @@ func EndpointsToString(endpoints *v2.Endpoints) string {
                return ip1 < ip2
        })
        for i, addr := range addresses {
-               sb.WriteString(fmt.Sprintf("%s:%d", addr.Host, addr.Port))
+               sb.WriteString(net.JoinHostPort(addr.Host, fmt.Sprintf("%d", 
addr.Port)))
                if i != len(addresses)-1 {
                        sb.WriteString(";")
                }
diff --git a/golang/pkg/utils/utils_test.go b/golang/pkg/utils/utils_test.go
index e8a53fa7..0456548b 100644
--- a/golang/pkg/utils/utils_test.go
+++ b/golang/pkg/utils/utils_test.go
@@ -94,6 +94,90 @@ func TestParseTarget(t *testing.T) {
        } else if !CompareEndpoints(endpointsExpect, endpoints) {
                t.Errorf("Expected endpoints: %v, but got: %v", 
endpointsExpect, endpoints)
        }
+
+       endpointIpv6Expect := &v2.Endpoints{
+               Scheme: v2.AddressScheme_IPv6,
+               Addresses: []*v2.Address{
+                       {
+                               Host: "fe80::1ff:fe23:4567:890a",
+                               Port: 80,
+                       },
+                       {
+                               Host: "2001:db8:abcd:12:1234:5678:9abc:def0",
+                               Port: 80,
+                       },
+               },
+       }
+       endpointIpv6s, err := 
ParseTarget("[fe80::1ff:fe23:4567:890a]:80;[2001:db8:abcd:12:1234:5678:9abc:def0]:80")
+       if err != nil {
+               t.Error(err)
+       } else if !CompareEndpoints(endpointIpv6Expect, endpointIpv6s) {
+               t.Errorf("Expected endpoints: %v, but got: %v", 
endpointIpv6Expect, endpointIpv6s)
+       }
+
+       endpointIpv6sWithHttpExpect := &v2.Endpoints{
+               Scheme: v2.AddressScheme_IPv6,
+               Addresses: []*v2.Address{
+                       {
+                               Host: "fe80::1ff:fe23:4567:890a",
+                               Port: 80,
+                       },
+               },
+       }
+       endpointIpv6sWithHttp, err := 
ParseTarget("http://[fe80::1ff:fe23:4567:890a]:80";)
+       if err != nil {
+               t.Error(err)
+       } else if !CompareEndpoints(endpointIpv6sWithHttpExpect, 
endpointIpv6sWithHttp) {
+               t.Errorf("Expected endpoints: %v, but got: %v", 
endpointIpv6sWithHttpExpect, endpointIpv6sWithHttp)
+       }
+
+       endpointWithDomainExpect := &v2.Endpoints{
+               Scheme: v2.AddressScheme_DOMAIN_NAME,
+               Addresses: []*v2.Address{
+                       {
+                               Host: "rocketmq-xxxxx.rocketmq.com",
+                               Port: 80,
+                       },
+               },
+       }
+       endpointWithDomain, err := ParseTarget("rocketmq-xxxxx.rocketmq.com:80")
+       if err != nil {
+               t.Error(err)
+       } else if !CompareEndpoints(endpointWithDomainExpect, 
endpointWithDomain) {
+               t.Errorf("Expected endpoints: %v, but got: %v", 
endpointWithDomain, endpointWithDomain)
+       }
+}
+
+func TestEndpointsToString(t *testing.T) {
+       endpoints := &v2.Endpoints{
+               Scheme: v2.AddressScheme_IPv4,
+               Addresses: []*v2.Address{
+                       {
+                               Host: "127.0.0.1",
+                               Port: 80,
+                       },
+               },
+       }
+       expected := "127.0.0.1:80"
+       actual := EndpointsToString(endpoints)
+       if actual != expected {
+               t.Errorf("Expected %s, but got %s", expected, actual)
+       }
+
+       endpointsIpv6 := &v2.Endpoints{
+               Scheme: v2.AddressScheme_IPv6,
+               Addresses: []*v2.Address{
+                       {
+                               Host: "fe80::1ff:fe23:4567:890a",
+                               Port: 80,
+                       },
+               },
+       }
+       ipv6Actual := EndpointsToString(endpointsIpv6)
+       endpointsIpv6Expected := "[fe80::1ff:fe23:4567:890a]:80"
+       if ipv6Actual != endpointsIpv6Expected {
+               t.Errorf("Expected %s, but got %s", endpointsIpv6Expected, 
ipv6Actual)
+       }
 }
 
 func TestMatchMessageType(t *testing.T) {

Reply via email to