mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-23 22:27:38 -05:00
add Header proxy policy
This commit is contained in:
parent
a6ec51b349
commit
95366e41c4
4 changed files with 73 additions and 10 deletions
|
@ -18,12 +18,13 @@ type Policy interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
RegisterPolicy("random", func() Policy { return &Random{} })
|
RegisterPolicy("random", func(arg string) Policy { return &Random{} })
|
||||||
RegisterPolicy("least_conn", func() Policy { return &LeastConn{} })
|
RegisterPolicy("least_conn", func(arg string) Policy { return &LeastConn{} })
|
||||||
RegisterPolicy("round_robin", func() Policy { return &RoundRobin{} })
|
RegisterPolicy("round_robin", func(arg string) Policy { return &RoundRobin{} })
|
||||||
RegisterPolicy("ip_hash", func() Policy { return &IPHash{} })
|
RegisterPolicy("ip_hash", func(arg string) Policy { return &IPHash{} })
|
||||||
RegisterPolicy("first", func() Policy { return &First{} })
|
RegisterPolicy("first", func(arg string) Policy { return &First{} })
|
||||||
RegisterPolicy("uri_hash", func() Policy { return &URIHash{} })
|
RegisterPolicy("uri_hash", func(arg string) Policy { return &URIHash{} })
|
||||||
|
RegisterPolicy("header", func(arg string) Policy { return &Header{arg} })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Random is a policy that selects up hosts from a pool at random.
|
// Random is a policy that selects up hosts from a pool at random.
|
||||||
|
@ -160,3 +161,22 @@ func (r *First) Select(pool HostPool, request *http.Request) *UpstreamHost {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Header is a policy that selects based on a hash of the given header
|
||||||
|
type Header struct {
|
||||||
|
// The name of the request header, the value of which will determine
|
||||||
|
// how the request is routed
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select selects the host based on hashing the header value
|
||||||
|
func (r *Header) Select(pool HostPool, request *http.Request) *UpstreamHost {
|
||||||
|
if r.Name == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
val := request.Header.Get(r.Name)
|
||||||
|
if val == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return hostByHashing(pool, val)
|
||||||
|
}
|
||||||
|
|
|
@ -302,3 +302,42 @@ func TestUriPolicy(t *testing.T) {
|
||||||
t.Error("Expected uri policy policy host to be nil.")
|
t.Error("Expected uri policy policy host to be nil.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHeaderPolicy(t *testing.T) {
|
||||||
|
pool := testPool()
|
||||||
|
tests := []struct {
|
||||||
|
Policy *Header
|
||||||
|
RequestHeaderName string
|
||||||
|
RequestHeaderValue string
|
||||||
|
NilHost bool
|
||||||
|
HostIndex int
|
||||||
|
}{
|
||||||
|
{&Header{""}, "", "", true, 0},
|
||||||
|
{&Header{""}, "Affinity", "somevalue", true, 0},
|
||||||
|
{&Header{""}, "Affinity", "", true, 0},
|
||||||
|
|
||||||
|
{&Header{"Affinity"}, "", "", true, 0},
|
||||||
|
{&Header{"Affinity"}, "Affinity", "somevalue", false, 1},
|
||||||
|
{&Header{"Affinity"}, "Affinity", "somevalue2", false, 0},
|
||||||
|
{&Header{"Affinity"}, "Affinity", "somevalue3", false, 2},
|
||||||
|
{&Header{"Affinity"}, "Affinity", "", true, 0},
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx, test := range tests {
|
||||||
|
request, _ := http.NewRequest("GET", "/", nil)
|
||||||
|
if test.RequestHeaderName != "" {
|
||||||
|
request.Header.Add(test.RequestHeaderName, test.RequestHeaderValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
host := test.Policy.Select(pool, request)
|
||||||
|
if test.NilHost && host != nil {
|
||||||
|
t.Errorf("%d: Expected host to be nil", idx)
|
||||||
|
}
|
||||||
|
if !test.NilHost && host == nil {
|
||||||
|
t.Errorf("%d: Did not expect host to be nil", idx)
|
||||||
|
}
|
||||||
|
if !test.NilHost && host != pool[test.HostIndex] {
|
||||||
|
t.Errorf("%d: Expected Header policy to be host %d", idx, test.HostIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
supportedPolicies = make(map[string]func() Policy)
|
supportedPolicies = make(map[string]func(string) Policy)
|
||||||
)
|
)
|
||||||
|
|
||||||
type staticUpstream struct {
|
type staticUpstream struct {
|
||||||
|
@ -243,7 +243,11 @@ func parseBlock(c *caddyfile.Dispenser, u *staticUpstream) error {
|
||||||
if !ok {
|
if !ok {
|
||||||
return c.ArgErr()
|
return c.ArgErr()
|
||||||
}
|
}
|
||||||
u.Policy = policyCreateFunc()
|
arg := ""
|
||||||
|
if c.NextArg() {
|
||||||
|
arg = c.Val()
|
||||||
|
}
|
||||||
|
u.Policy = policyCreateFunc(arg)
|
||||||
case "fail_timeout":
|
case "fail_timeout":
|
||||||
if !c.NextArg() {
|
if !c.NextArg() {
|
||||||
return c.ArgErr()
|
return c.ArgErr()
|
||||||
|
@ -523,7 +527,7 @@ func (u *staticUpstream) Stop() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterPolicy adds a custom policy to the proxy.
|
// RegisterPolicy adds a custom policy to the proxy.
|
||||||
func RegisterPolicy(name string, policy func() Policy) {
|
func RegisterPolicy(name string, policy func(string) Policy) {
|
||||||
supportedPolicies[name] = policy
|
supportedPolicies[name] = policy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,7 @@ func TestSelect(t *testing.T) {
|
||||||
func TestRegisterPolicy(t *testing.T) {
|
func TestRegisterPolicy(t *testing.T) {
|
||||||
name := "custom"
|
name := "custom"
|
||||||
customPolicy := &customPolicy{}
|
customPolicy := &customPolicy{}
|
||||||
RegisterPolicy(name, func() Policy { return customPolicy })
|
RegisterPolicy(name, func(string) Policy { return customPolicy })
|
||||||
if _, ok := supportedPolicies[name]; !ok {
|
if _, ok := supportedPolicies[name]; !ok {
|
||||||
t.Error("Expected supportedPolicies to have a custom policy.")
|
t.Error("Expected supportedPolicies to have a custom policy.")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue