Skip to content

Commit

Permalink
fixed bug in resolving ip version in dynamic upstreams
Browse files Browse the repository at this point in the history
  • Loading branch information
armadi1809 committed Jul 9, 2024
1 parent 9338741 commit 23fa658
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 12 deletions.
26 changes: 14 additions & 12 deletions modules/caddyhttp/reverseproxy/upstreams.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,9 +313,6 @@ func (au *AUpstreams) Provision(ctx caddy.Context) error {
func (au AUpstreams) GetUpstreams(r *http.Request) ([]*Upstream, error) {
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.
// This should be fairly inexpensive and comes and the upside of
// allowing the same dynamic upstream (name + port combination)
Expand All @@ -324,15 +321,7 @@ func (au AUpstreams) GetUpstreams(r *http.Request) ([]*Upstream, error) {
// It also forced a cache-miss if a previously cached dynamic
// upstream changes its ip version, e.g. after a config reload,
// while keeping the cache-invalidation as simple as it currently is.
var ipVersion string
switch {
case resolveIpv4 && !resolveIpv6:
ipVersion = "ip4"
case !resolveIpv4 && resolveIpv6:
ipVersion = "ip6"
default:
ipVersion = "ip"
}
ipVersion := resolveIpVersion(au.Versions)

auStr := repl.ReplaceAll(au.String()+ipVersion, "")

Expand Down Expand Up @@ -397,6 +386,19 @@ func (au AUpstreams) GetUpstreams(r *http.Request) ([]*Upstream, error) {

func (au AUpstreams) String() string { return net.JoinHostPort(au.Name, au.Port) }

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"
}
}

type aLookup struct {
aUpstreams AUpstreams
freshness time.Time
Expand Down
48 changes: 48 additions & 0 deletions modules/caddyhttp/reverseproxy/upstreams_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
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: &trueBool, IPv6: &falseBool},
expectedIpVersion: "ip4",
},
{
Versions: &IPVersions{IPv6: &trueBool},
expectedIpVersion: "ip6",
},
{
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)
}
}

}

0 comments on commit 23fa658

Please # to comment.