mirror of
https://github.com/yusing/godoxy.git
synced 2025-05-20 04:42:33 +02:00
63 lines
1.2 KiB
Go
63 lines
1.2 KiB
Go
package health
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"errors"
|
|
"net/http"
|
|
|
|
"github.com/yusing/go-proxy/internal/net/types"
|
|
)
|
|
|
|
type HTTPHealthMonitor struct {
|
|
*monitor
|
|
method string
|
|
pinger *http.Client
|
|
}
|
|
|
|
func NewHTTPHealthMonitor(ctx context.Context, name string, url types.URL, config HealthCheckConfig) HealthMonitor {
|
|
mon := new(HTTPHealthMonitor)
|
|
mon.monitor = newMonitor(ctx, name, url, &config, mon.checkHealth)
|
|
mon.pinger = &http.Client{Timeout: config.Timeout}
|
|
if config.UseGet {
|
|
mon.method = http.MethodGet
|
|
} else {
|
|
mon.method = http.MethodHead
|
|
}
|
|
return mon
|
|
}
|
|
|
|
func (mon *HTTPHealthMonitor) checkHealth() (healthy bool, detail string, err error) {
|
|
req, reqErr := http.NewRequestWithContext(
|
|
mon.ctx,
|
|
mon.method,
|
|
mon.URL.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
|
|
}
|