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) {