GoDoxy/internal/watcher/health/http.go
yusing 53557e38b6 Fixed a few issues:
- Incorrect name being shown on dashboard "Proxies page"
- Apps being shown when homepage.show is false
- Load balanced routes are shown on homepage instead of the load balancer
- Route with idlewatcher will now be removed on container destroy
- Idlewatcher panic
- Performance improvement
- Idlewatcher infinitely loading
- Reload stucked / not working properly
- Streams stuck on shutdown / reload
- etc...
Added:
- support idlewatcher for loadbalanced routes
- partial implementation for stream type idlewatcher
Issues:
- graceful shutdown
2024-10-18 16:47:01 +08:00

69 lines
1.5 KiB
Go

package health
import (
"crypto/tls"
"errors"
"net/http"
"github.com/yusing/go-proxy/internal/net/types"
)
type HTTPHealthMonitor struct {
*monitor
method string
pinger *http.Client
}
func NewHTTPHealthMonitor(url types.URL, config *HealthCheckConfig, transport http.RoundTripper) *HTTPHealthMonitor {
mon := new(HTTPHealthMonitor)
mon.monitor = newMonitor(url, config, mon.CheckHealth)
mon.pinger = &http.Client{Timeout: config.Timeout, Transport: transport}
if config.UseGet {
mon.method = http.MethodGet
} else {
mon.method = http.MethodHead
}
return mon
}
func NewHTTPHealthChecker(url types.URL, config *HealthCheckConfig, transport http.RoundTripper) HealthChecker {
return NewHTTPHealthMonitor(url, config, transport)
}
func (mon *HTTPHealthMonitor) CheckHealth() (healthy bool, detail string, err error) {
ctx, cancel := mon.ContextWithTimeout("ping request timed out")
defer cancel()
req, reqErr := http.NewRequestWithContext(
ctx,
mon.method,
mon.url.Load().JoinPath(mon.config.Path).String(),
nil,
)
if reqErr != nil {
err = reqErr
return
}
req.Header.Set("Connection", "close")
resp, respErr := mon.pinger.Do(req)
if respErr == nil {
resp.Body.Close()
}
switch {
case respErr != nil:
// treat tls error as healthy
var tlsErr *tls.CertificateVerificationError
if ok := errors.As(respErr, &tlsErr); !ok {
detail = respErr.Error()
return
}
case resp.StatusCode == http.StatusServiceUnavailable:
detail = resp.Status
return
}
healthy = true
return
}