mirror of
https://github.com/redis/go-redis.git
synced 2025-09-05 20:24:00 +03:00
fix(client): Do not assume that all non-IP hosts are loopbacks (#3085)
* Do not assume that all non-IP hosts are loopbacks * handle localhost and Docker internal hostnames --------- Co-authored-by: Nedyalko Dyakov <nedyalko.dyakov@gmail.com> Co-authored-by: Nedyalko Dyakov <1547186+ndyakov@users.noreply.github.com> Co-authored-by: ofekshenawa <ofek.shenawa@redis.com> Co-authored-by: ofekshenawa <104765379+ofekshenawa@users.noreply.github.com>
This commit is contained in:
@@ -383,3 +383,38 @@ var _ = Describe("ClusterClient", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
var _ = Describe("isLoopback", func() {
|
||||||
|
DescribeTable("should correctly identify loopback addresses",
|
||||||
|
func(host string, expected bool) {
|
||||||
|
result := isLoopback(host)
|
||||||
|
Expect(result).To(Equal(expected))
|
||||||
|
},
|
||||||
|
// IP addresses
|
||||||
|
Entry("IPv4 loopback", "127.0.0.1", true),
|
||||||
|
Entry("IPv6 loopback", "::1", true),
|
||||||
|
Entry("IPv4 non-loopback", "192.168.1.1", false),
|
||||||
|
Entry("IPv6 non-loopback", "2001:db8::1", false),
|
||||||
|
|
||||||
|
// Well-known loopback hostnames
|
||||||
|
Entry("localhost lowercase", "localhost", true),
|
||||||
|
Entry("localhost uppercase", "LOCALHOST", true),
|
||||||
|
Entry("localhost mixed case", "LocalHost", true),
|
||||||
|
|
||||||
|
// Docker-specific loopbacks
|
||||||
|
Entry("host.docker.internal", "host.docker.internal", true),
|
||||||
|
Entry("HOST.DOCKER.INTERNAL", "HOST.DOCKER.INTERNAL", true),
|
||||||
|
Entry("custom.docker.internal", "custom.docker.internal", true),
|
||||||
|
Entry("app.docker.internal", "app.docker.internal", true),
|
||||||
|
|
||||||
|
// Non-loopback hostnames
|
||||||
|
Entry("redis hostname", "redis-cluster", false),
|
||||||
|
Entry("FQDN", "redis.example.com", false),
|
||||||
|
Entry("docker but not internal", "redis.docker.com", false),
|
||||||
|
|
||||||
|
// Edge cases
|
||||||
|
Entry("empty string", "", false),
|
||||||
|
Entry("invalid IP", "256.256.256.256", false),
|
||||||
|
Entry("partial docker internal", "docker.internal", false),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
@@ -781,12 +781,25 @@ func replaceLoopbackHost(nodeAddr, originHost string) string {
|
|||||||
return net.JoinHostPort(originHost, nodePort)
|
return net.JoinHostPort(originHost, nodePort)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isLoopback returns true if the host is a loopback address.
|
||||||
|
// For IP addresses, it uses net.IP.IsLoopback().
|
||||||
|
// For hostnames, it recognizes well-known loopback hostnames like "localhost"
|
||||||
|
// and Docker-specific loopback patterns like "*.docker.internal".
|
||||||
func isLoopback(host string) bool {
|
func isLoopback(host string) bool {
|
||||||
ip := net.ParseIP(host)
|
ip := net.ParseIP(host)
|
||||||
if ip == nil {
|
if ip != nil {
|
||||||
|
return ip.IsLoopback()
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.ToLower(host) == "localhost" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return ip.IsLoopback()
|
|
||||||
|
if strings.HasSuffix(strings.ToLower(host), ".docker.internal") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clusterState) slotMasterNode(slot int) (*clusterNode, error) {
|
func (c *clusterState) slotMasterNode(slot int) (*clusterNode, error) {
|
||||||
|
Reference in New Issue
Block a user