diff --git a/caddyhttp/proxy/policy.go b/caddyhttp/proxy/policy.go index 337ad1e8..37715bb6 100644 --- a/caddyhttp/proxy/policy.go +++ b/caddyhttp/proxy/policy.go @@ -22,6 +22,7 @@ func init() { RegisterPolicy("least_conn", func() Policy { return &LeastConn{} }) RegisterPolicy("round_robin", func() Policy { return &RoundRobin{} }) RegisterPolicy("ip_hash", func() Policy { return &IPHash{} }) + RegisterPolicy("first", func() Policy { return &First{} }) } // Random is a policy that selects up hosts from a pool at random. @@ -131,3 +132,16 @@ func (r *IPHash) Select(pool HostPool, request *http.Request) *UpstreamHost { } return nil } + +// First is a policy that selects the fist available host +type First struct{} + +// Select selects the first host from the pool, that is available +func (r *First) Select(pool HostPool, request *http.Request) *UpstreamHost { + for _, host := range pool { + if host.Available() { + return host + } + } + return nil +} diff --git a/caddyhttp/proxy/policy_test.go b/caddyhttp/proxy/policy_test.go index 9b277197..1db7c29f 100644 --- a/caddyhttp/proxy/policy_test.go +++ b/caddyhttp/proxy/policy_test.go @@ -226,3 +226,20 @@ func TestIPHashPolicy(t *testing.T) { t.Error("Expected ip hash policy host to be nil.") } } + +func TestFirstPolicy(t *testing.T) { + pool := testPool() + firstPolicy := &First{} + req := httptest.NewRequest(http.MethodGet, "/", nil) + + h := firstPolicy.Select(pool, req) + if h != pool[0] { + t.Error("Expected first policy host to be the first host.") + } + + pool[0].Unhealthy = 1 + h = firstPolicy.Select(pool, req) + if h != pool[1] { + t.Error("Expected first policy host to be the second host.") + } +}