fixed bug in resolving ip version in dynamic upstreams (#6448)

This commit is contained in:
Aziz Rmadi 2024-07-09 02:06:30 -05:00 committed by GitHub
parent 9338741ca7
commit 630c62b313
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 70 additions and 12 deletions

View file

@ -231,6 +231,19 @@ type IPVersions struct {
IPv6 *bool `json:"ipv6,omitempty"` IPv6 *bool `json:"ipv6,omitempty"`
} }
func resolveIpVersion(versions *IPVersions) string {
resolveIpv4 := versions == nil || (versions.IPv4 == nil && versions.IPv6 == nil) || (versions.IPv4 != nil && *versions.IPv4)
resolveIpv6 := versions == nil || (versions.IPv6 == nil && versions.IPv4 == nil) || (versions.IPv6 != nil && *versions.IPv6)
switch {
case resolveIpv4 && !resolveIpv6:
return "ip4"
case !resolveIpv4 && resolveIpv6:
return "ip6"
default:
return "ip"
}
}
// AUpstreams provides upstreams from A/AAAA lookups. // AUpstreams provides upstreams from A/AAAA lookups.
// Results are cached and refreshed at the configured // Results are cached and refreshed at the configured
// refresh interval. // refresh interval.
@ -313,9 +326,6 @@ func (au *AUpstreams) Provision(ctx caddy.Context) error {
func (au AUpstreams) GetUpstreams(r *http.Request) ([]*Upstream, error) { func (au AUpstreams) GetUpstreams(r *http.Request) ([]*Upstream, error) {
repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer) repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
resolveIpv4 := au.Versions == nil || au.Versions.IPv4 == nil || *au.Versions.IPv4
resolveIpv6 := au.Versions == nil || au.Versions.IPv6 == nil || *au.Versions.IPv6
// Map ipVersion early, so we can use it as part of the cache-key. // Map ipVersion early, so we can use it as part of the cache-key.
// This should be fairly inexpensive and comes and the upside of // This should be fairly inexpensive and comes and the upside of
// allowing the same dynamic upstream (name + port combination) // allowing the same dynamic upstream (name + port combination)
@ -324,15 +334,7 @@ func (au AUpstreams) GetUpstreams(r *http.Request) ([]*Upstream, error) {
// It also forced a cache-miss if a previously cached dynamic // It also forced a cache-miss if a previously cached dynamic
// upstream changes its ip version, e.g. after a config reload, // upstream changes its ip version, e.g. after a config reload,
// while keeping the cache-invalidation as simple as it currently is. // while keeping the cache-invalidation as simple as it currently is.
var ipVersion string ipVersion := resolveIpVersion(au.Versions)
switch {
case resolveIpv4 && !resolveIpv6:
ipVersion = "ip4"
case !resolveIpv4 && resolveIpv6:
ipVersion = "ip6"
default:
ipVersion = "ip"
}
auStr := repl.ReplaceAll(au.String()+ipVersion, "") auStr := repl.ReplaceAll(au.String()+ipVersion, "")

View file

@ -0,0 +1,56 @@
package reverseproxy
import "testing"
func TestResolveIpVersion(t *testing.T) {
falseBool := false
trueBool := true
tests := []struct {
Versions *IPVersions
expectedIpVersion string
}{
{
Versions: &IPVersions{IPv4: &trueBool},
expectedIpVersion: "ip4",
},
{
Versions: &IPVersions{IPv4: &falseBool},
expectedIpVersion: "ip",
},
{
Versions: &IPVersions{IPv4: &trueBool, IPv6: &falseBool},
expectedIpVersion: "ip4",
},
{
Versions: &IPVersions{IPv6: &trueBool},
expectedIpVersion: "ip6",
},
{
Versions: &IPVersions{IPv6: &falseBool},
expectedIpVersion: "ip",
},
{
Versions: &IPVersions{IPv6: &trueBool, IPv4: &falseBool},
expectedIpVersion: "ip6",
},
{
Versions: &IPVersions{},
expectedIpVersion: "ip",
},
{
Versions: &IPVersions{IPv4: &trueBool, IPv6: &trueBool},
expectedIpVersion: "ip",
},
{
Versions: &IPVersions{IPv4: &falseBool, IPv6: &falseBool},
expectedIpVersion: "ip",
},
}
for _, test := range tests {
ipVersion := resolveIpVersion(test.Versions)
if ipVersion != test.expectedIpVersion {
t.Errorf("resolveIpVersion(): Expected %s got %s", test.expectedIpVersion, ipVersion)
}
}
}