caddy/middleware/proxy/upstream.go

80 lines
1.4 KiB
Go
Raw Normal View History

package proxy
import (
"io"
"io/ioutil"
"net/http"
"time"
)
type StaticUpstream struct {
From string
Hosts HostPool
Policy Policy
FailTimeout time.Duration
MaxFails int32
HealthCheck struct {
Path string
Interval time.Duration
}
}
func (u *StaticUpstream) from() string {
return u.From
}
func (u *StaticUpstream) healthCheck() {
for _, host := range u.Hosts {
hostUrl := host.Name + u.HealthCheck.Path
if r, err := http.Get(hostUrl); err == nil {
io.Copy(ioutil.Discard, r.Body)
r.Body.Close()
host.Unhealthy = r.StatusCode < 200 || r.StatusCode >= 400
} else {
host.Unhealthy = true
}
}
}
func (u *StaticUpstream) HealthCheckWorker(stop chan struct{}) {
ticker := time.NewTicker(u.HealthCheck.Interval)
u.healthCheck()
for {
select {
case <-ticker.C:
u.healthCheck()
case <-stop:
// TODO: the library should provide a stop channel and global
// waitgroup to allow goroutines started by plugins a chance
// to clean themselves up.
}
}
}
func (u *StaticUpstream) Select() *UpstreamHost {
pool := u.Hosts
if len(pool) == 1 {
if pool[0].Down() {
return nil
}
return pool[0]
}
allDown := true
for _, host := range pool {
if !host.Down() {
allDown = false
break
}
}
if allDown {
return nil
}
if u.Policy == nil {
return (&Random{}).Select(pool)
} else {
return u.Policy.Select(pool)
}
}