Skip to content

Commit 0783c24

Browse files
committed
handle localhost and Docker internal hostnames
1 parent cec431e commit 0783c24

File tree

2 files changed

+51
-3
lines changed

2 files changed

+51
-3
lines changed

internal_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,3 +376,38 @@ var _ = Describe("ClusterClient", func() {
376376
})
377377
})
378378
})
379+
380+
var _ = Describe("isLoopback", func() {
381+
DescribeTable("should correctly identify loopback addresses",
382+
func(host string, expected bool) {
383+
result := isLoopback(host)
384+
Expect(result).To(Equal(expected))
385+
},
386+
// IP addresses
387+
Entry("IPv4 loopback", "127.0.0.1", true),
388+
Entry("IPv6 loopback", "::1", true),
389+
Entry("IPv4 non-loopback", "192.168.1.1", false),
390+
Entry("IPv6 non-loopback", "2001:db8::1", false),
391+
392+
// Well-known loopback hostnames
393+
Entry("localhost lowercase", "localhost", true),
394+
Entry("localhost uppercase", "LOCALHOST", true),
395+
Entry("localhost mixed case", "LocalHost", true),
396+
397+
// Docker-specific loopbacks
398+
Entry("host.docker.internal", "host.docker.internal", true),
399+
Entry("HOST.DOCKER.INTERNAL", "HOST.DOCKER.INTERNAL", true),
400+
Entry("custom.docker.internal", "custom.docker.internal", true),
401+
Entry("app.docker.internal", "app.docker.internal", true),
402+
403+
// Non-loopback hostnames
404+
Entry("redis hostname", "redis-cluster", false),
405+
Entry("FQDN", "redis.example.com", false),
406+
Entry("docker but not internal", "redis.docker.com", false),
407+
408+
// Edge cases
409+
Entry("empty string", "", false),
410+
Entry("invalid IP", "256.256.256.256", false),
411+
Entry("partial docker internal", "docker.internal", false),
412+
)
413+
})

osscluster.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -741,12 +741,25 @@ func replaceLoopbackHost(nodeAddr, originHost string) string {
741741
return net.JoinHostPort(originHost, nodePort)
742742
}
743743

744+
// isLoopback returns true if the host is a loopback address.
745+
// For IP addresses, it uses net.IP.IsLoopback().
746+
// For hostnames, it recognizes well-known loopback hostnames like "localhost"
747+
// and Docker-specific loopback patterns like "*.docker.internal".
744748
func isLoopback(host string) bool {
745749
ip := net.ParseIP(host)
746-
if ip == nil {
747-
return false
750+
if ip != nil {
751+
return ip.IsLoopback()
748752
}
749-
return ip.IsLoopback()
753+
754+
if strings.ToLower(host) == "localhost" {
755+
return true
756+
}
757+
758+
if strings.HasSuffix(strings.ToLower(host), ".docker.internal") {
759+
return true
760+
}
761+
762+
return false
750763
}
751764

752765
func (c *clusterState) slotMasterNode(slot int) (*clusterNode, error) {

0 commit comments

Comments
 (0)